需求:用户需要下载服务器上的文件,可以单独下载,批量下载,可以暂停,涉及要点IO流,HTTP协议。
- 准备工作
几个要下载的文件,搭好javaweb框架
2.单文件的下载
传入参数path为文件的服务器上的绝对路径,包括扩展名,也就是需要传输的文件,
public void downOneFile(HttpServletResponse resp, HttpServletRequest req,String path) throws IOException{
File f = new File(path);
FileInputStream fis = new FileInputStream(f);
response.reset();
response.setHeader("Server", "siyu");
response.setHeader("Accept-Ranges", "bytes");
long p = 0;
long l = 0;
l = f.length();
if (request.getHeader("Range") != null)
{
response.setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT);// 206
p = Long.parseLong(request.getHeader("Range").replaceAll("bytes=", "").replaceAll("-", ""));
}
response.setHeader("Content-Length", new Long(l - p).toString());
if (p != 0) {
response.setHeader("Content-Range", "bytes " + new Long(p).toString() + "-"
+ new Long(l - 1).toString() + "/" + new Long(l).toString());
}
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" + f.getName());
fis.skip(p);
byte[] b = new byte[1024];
int i;
while ((i = fis.read(b)) != -1) {
response.getOutputStream().write(b, 0, i);
}
if(i==-1){//下载完成做的事情
}
fis.close();
}
简单测试:请求此方法浏览器会弹出下载框,可暂停后继续下载
@RequestMapping(value="down")
public void test(HttpServletResponse rsp, HttpServletRequest req){
String paths=req.getSession().getServletContext().getRealPath("/");//获取项目绝对路径
String path=paths+"video/1.mp4";
downOneFile(rsp,req,path)
}
3.打包下载
原理一样的,就是将多个要下载的文件提取出来,在后台打包成一个zip形式的压缩文件,在浏览器中也就是下载单个文件
具体怎么打包,一可用java自带的工具包,二可下载org-apache-zip-1.9.4.jar该工具包推荐使用。打包的大致过程(1)创建一个File[]数组,将需要下载的所有文件的放进去,然后写入到压缩包中,写完之后再调用单个下载的方法,就是这么简单。
//---打包的方法
public void makezip() throws IOException{
ZipOutputStream out=null;
FileInputStream fis=null;
String tmpFileName ="temp.zip"; //设置临时的打包文件及名称
//获取所有需要打包文件的路径,存储在数组中
File[] file1=new File[2];
file1[0]=new File("D:\\1.txt");
file1[1]=new File("D:\\2.txt");
byte[] buffer = new byte[1024];
//路径,压缩包临时存储位置
String zipPath = "E:\\"+ tmpFileName;
//-----将可打包的文件打包-
try{
out = new ZipOutputStream(new FileOutputStream(
zipPath));
for (int i = 0; i < file1.length; i++) {
fis = new FileInputStream(file1[i]);
out.putNextEntry(new ZipEntry(file1[i].getName()));
//设置压缩文件内的字符编码,中文名乱码问题
out.setEncoding("GBK");
int len;
// 读入需要文件的内容,写入到zip文件
while ((len = fis.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
}
}catch(IOException e){
e.printStackTrace();
}finally{
if(out!=null){
out.closeEntry();
out.close();
}
if(fis!=null){
fis.close();
}
}
}
4.多线程的方式
因为一次请求只能有一次响应。