文件壓縮後下載

最近項目裏面,增加一個文件壓縮下載的功能。拿出來跟大家分享。。。

項目框架: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();
				}
			}
		}
	}
}

 寫在最後,文件下載完成後,可以刪除生成的臨時文件。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章