java实现服务器文件打包zip并下载的示例(边打包边下载)
使用该方法,可以即时打包文件,一边打包一边传输,不使用任何的缓存,让用户零等待!
/**
*
* mysocket 客户端 socket
* @param file 待打包的文件夹或文件
* @param filename 打包下载的文件名
* @throws ioexception
*/
private void down(file file, string filename) throws ioexception {
outputstream outputstream = mysocket.getoutputstream();
stringbuffer sb = new stringbuffer("http/1.1 200 ok\r\n");
sb.append("server: java/1.1\r\n");
sb.append("content-type:application/octet-stream;charset=utf-8\r\n");
//sb.append("user-agent: mozilla/4.0 (compatible;msie6.0;windows nt 5.0)\r\n");
sb.append("content-disposition: attachment; filename=" + filename
+ "\r\n");
sb.append("transfer-encoding: chunked\r\n");
sb.append("connection: keep-alive\r\n\r\n");
outputstream.write(sb.tostring().getbytes());
outputstream.flush();
zipcompressor zipcompressor = new zipcompressor(new myoutputstream(
outputstream));
zipcompressor.compress(file);
system.out.println("zip end");
system.out.println("write '0\\r\\n\\r\\n'");
outputstream.write("0\r\n\r\n".getbytes());//transfer-encoding: chunked传输结束标记
outputstream.flush();
outputstream.close();
system.out.println("download stop");
try {
mysocket.close();
} catch (throwable t) {
}
}
package cn.liangjintang.webserver.zipfile;
import java.io.bufferedinputstream;
import java.io.file;
import java.io.fileinputstream;
import java.io.outputstream;
import java.lang.reflect.field;
import java.util.zip.crc32;
import java.util.zip.checkedoutputstream;
import java.util.zip.zipentry;
import java.util.zip.zipoutputstream;
public class zipcompressor {
static final int buffer = 8192;
private outputstream outputstream;
public zipcompressor(myoutputstream outputstream) {
this.outputstream=outputstream;
}
public void compress(file file) {
if (!file.exists())
throw new runtimeexception(file.getabsolutepath() + "不存在!");
try {
checkedoutputstream cos = new checkedoutputstream(outputstream,
new crc32());
zipoutputstream out = new zipoutputstream(cos);
string basedir = "";
compress(file, out, basedir);
out.close();//必须关闭,这样才会写入zip的结束信息,否则zip文件不完整.若想继续写入,可重写outputstream.close()方法
} catch (exception e) {
throw new runtimeexception(e);
}
}
private void compress(file file, zipoutputstream out, string basedir) {
//判断是目录还是文件
if (file.isdirectory()) {
system.out.println("压缩:" + basedir + file.getname());
this.compressdirectory(file, out, basedir);
} else {
system.out.println("压缩:" + basedir + file.getname());
this.compressfile(file, out, basedir);
}
}
// 压缩一个目录
private void compressdirectory(file dir, zipoutputstream out, string basedir) {
if (!dir.exists())
return;
file[] files = dir.listfiles();
for (int i = 0; i < files.length; i++) {
/** 递归 */
compress(files[i], out, basedir + dir.getname() + "/");
}
}
//压缩一个文件
private void compressfile(file file, zipoutputstream out, string basedir) {
if (!file.exists()) {
return;
}
try {
bufferedinputstream bis = new bufferedinputstream(
new fileinputstream(file));
zipentry entry = new zipentry(basedir + file.getname());
out.putnextentry(entry);
int count;
byte data[] = new byte[buffer];
while ((count = bis.read(data, 0, buffer)) != -1) {
out.write(data, 0, count);
}
bis.close();
} catch (exception e) {
throw new runtimeexception(e);
}
}
}
package cn.liangjintang.webserver.zipfile;
import java.io.filteroutputstream;
import java.io.ioexception;
import java.io.outputstream;
public class myoutputstream extends filteroutputstream {
public myoutputstream(outputstream out) {
super(out);
}
final byte[] onebytes = "1\r\n".getbytes();
final byte[] rnbytes = "\r\n".getbytes();
public void write(int b) throws ioexception {
out.write(onebytes);//字节数1+crlf
out.write(b);//数据实体
out.write(rnbytes);//crlf
}
public void write(byte[] b) throws ioexception {
out.write(integer.tohexstring(b.length).getbytes());//字节数,十六进制
out.write(rnbytes);//crlf
out.write(b);//数据实体
out.write(rnbytes);//crlf
}
public void write(byte[] b, int off, int len) throws ioexception {
out.write(integer.tohexstring(len - off).getbytes());//字节数,十六进制
out.write(rnbytes);//crlf
out.write(b, off, len);//数据实体
out.write(rnbytes);//crlf
}
/**
* 重写该方法,否则outputstream会被关闭,其他的数据<br/>
* (如transfer-encoding: chunked传输结束标记)就不能再继续写入了
*/
public void close() throws ioexception {
}
}