最近项目里面,增加一个文件压缩下载的功能。拿出来跟大家分享。。。
项目框架:springmvc+spring+mybatis
- jsp页面下载按钮
<a title="下载" href="${path }/admin/report-task/download?id=${item.id}"
class="btn btn-success radius size-S" style="text-decoration:none;">
<i class="Hui-iconfont Hui-iconfont-yundown"></i>
</a>
- 控制层下载方法,将上传后的文件拷贝到临时文件夹下面,生成压缩包,执行下载操作:
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
//下载方法,请忽略业务逻辑部分
@RequestMapping("/download")
@ResponseBody
public void donwload(@RequestParam(value="id")Integer id,
HttpServletResponse response) throws IOException{
OrgReportTask entity = this.orgReportTaskService.selectByPrimaryKey(id);
OrgReportObject param = new OrgReportObject();
param.setTaskId(id);
List<OrgReportObjectViewVo> list = this.orgReportObjectService.getList(param);
//任务ID,根据任务ID查询上报支部对象,根据支部上报对象获取下载文件
//创建任务名称临时文件夹
String rootPath = MyUploadUtils.getRootUploadPath(request);
String taskPath = rootPath+"/temp/"+entity.getTaskName();
File taskFile = new File(taskPath);
if(!taskFile.exists()) {
taskFile.mkdirs();
}
//创建组织名称临时文件夹,并将给组织上传文件,复制到临时文件夹
for(OrgReportObjectViewVo vo : list) {
String orgPath = taskPath + "/" + vo.getOrgName();
File orgFile = new File(orgPath);
if(!orgFile.exists()) {
orgFile.mkdirs();
}
//拷贝文件对象到临时文件夹
Map<String,Object> map = new HashMap<>();
map.put("tableId", vo.getId());
map.put("tableName", "org_report_object");
List<BscFile> fileList = this.bscFileService.getFileListByMap(map);
for(BscFile file:fileList) {
File source = new File(rootPath+file.getFileUrl());
File dest = new File(orgPath+"/"+file.getFileName());
FileUtils.copyFile(source, dest);
}
}
//生成压缩包,执行下载操作
zipDownload(response, entity.getTaskName(), taskFile);
}
/**
* 生成压缩包,执行下载操作
* @param response
* @param zipFileName 压缩包名称
* @param sourceFile 待压缩文件路径
*/
private void zipDownload(HttpServletResponse response,String zipFileName,File sourceFile) {
//响应头的设置
response.reset();
response.setCharacterEncoding("utf-8");
response.setContentType("multipart/form-data");
//设置压缩包的名字
zipFileName = zipFileName + ".zip";
//解决不同浏览器压缩包名字含有中文时乱码的问题
String agent = request.getHeader("USER-AGENT");
ZipOutputStream zipos = null;
DataOutputStream os = null;
InputStream is = null;
try {
if (agent.contains("MSIE")||agent.contains("Trident")) {
zipFileName = java.net.URLEncoder.encode(zipFileName, "UTF-8");
} else {
zipFileName = new String(zipFileName.getBytes("UTF-8"),"ISO-8859-1");
}
response.setHeader("Content-Disposition", "attachment;fileName=\"" + zipFileName + "\"");
//设置压缩流:直接写入response,实现边压缩边下载
zipos = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
zipos.setMethod(ZipOutputStream.DEFLATED); //设置压缩方法
//循环将文件写入压缩流
fileIterator(sourceFile, sourceFile.getName(), zipos, os, is);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(is!=null) is.close();
if(os!=null) os.close();
if(zipos!=null) zipos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* @description 递归调用遍历文件下文件
* @param sourceFile 文件夹
* @param zipPathTop 压缩文件夹内部目录最高层级
* @param zipos
* @param os
* @param is
*/
public void fileIterator(File sourceFile,String zipPathTop,ZipOutputStream zipos,DataOutputStream os, InputStream is) {
//循环将文件写入压缩流
File[] deviceFiles = sourceFile.listFiles();
if(deviceFiles != null && deviceFiles.length != 0){
for(File file:deviceFiles) {//获取路径下各文件夹
if(file.isDirectory()) {//判断是否是路径,遍历路径
fileIterator(file,zipPathTop,zipos,os,is);
}else {//文件,直接压缩
try {
//压缩后的文件保留现有目录结构
String zipPath =file.getPath().substring(file.getPath().indexOf(zipPathTop));
zipos.putNextEntry(new ZipEntry(zipPath));
os = new DataOutputStream(zipos);
is = new FileInputStream(file);
byte[] b = new byte[100];
int length = 0;
while((length = is.read(b))!= -1){
os.write(b, 0, length);
}
os.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
写在最后,文件下载完成后,可以删除生成的临时文件。。。