最近項目裏面,增加一個文件壓縮下載的功能。拿出來跟大家分享。。。
項目框架: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();
}
}
}
}
}
寫在最後,文件下載完成後,可以刪除生成的臨時文件。。。