最近做了一些有關批量壓縮下載的功能,網上也找了一些資源,但都不是太全面,所以自己整理一份,已備不時之需。
直接上代碼:
// 獲取項目路徑
private static String WEBCLASS_PATH = Thread.currentThread().getContextClassLoader().getResource("").getPath();
// 獲取webinf路徑
private static String WEBINF_PATH = WEBCLASS_PATH.substring(0, WEBCLASS_PATH.lastIndexOf("classes"));
// 獲取upload路徑
private static String UPLOAD_PATH = WEBINF_PATH.substring(0, WEBINF_PATH.lastIndexOf("WEB-INF")) + "upload/";
public void downloadAllFiles(HttpServletRequest request, HttpServletResponse response) {
// 獲取要下載的文件對應的信息ID-選中文件ID拼接的字符串
String lessionIdStr = request.getParameter("fileIds");
// 第一個文件的文件名
String firstFileName = "";
List<UploadFileInfo> downLoadFiles = new LinkedList<UploadFileInfo>();
if (StringUtil.isNotEmpty(lessionIdStr)) {
int end = lessionIdStr.lastIndexOf(",");
if (end > 0) {
if (end == lessionIdStr.length() - 1) {
lessionIdStr = lessionIdStr.substring(0, end);
}
String[] ids = lessionIdStr.split(",");
for (int i = 0; i < ids.length; i++) {
// 循環獲取每一個文件信息
UploadFileInfo fileInfo = uploadFileInfoService.selectByPrimaryKey(ids[i]);
if (fileInfo != null) {
downLoadFiles.add(fileInfo);
}
if (i == 0) {
firstFileName = fileInfo.getFileName().substring(0, fileInfo.getFileName().lastIndexOf("."));
}
}
}else {
// 循環獲取每一個文件信息
UploadFileInfo fileInfo = uploadFileInfoService.selectByPrimaryKey(lessionIdStr);
if (fileInfo != null) {
downLoadFiles.add(fileInfo);
}
firstFileName = fileInfo.getFileName().substring(0, fileInfo.getFileName().lastIndexOf("."));
}
}
// 有數據可以下載
if (downLoadFiles.size() != 0) {
// 進行預處理
preProcess(firstFileName, response);
// 壓縮處理
writeZip(downLoadFiles);
// 下載文件
downFile(response);
// 刪除臨時壓縮文件
afterProcess();
}
}
// 壓縮文件輸出流
private ZipOutputStream out;
// 臨時壓縮文件存儲路徑
private String filePath;
/**
* 描述: 預處理
* 參數: @param firseFileName 批量下載的第一個文件名
* 參數: @param response
*/
private void preProcess(String firseFileName, HttpServletResponse response) {
// 壓縮文件名稱
String zipName = "【批量下載】" + firseFileName + "等.zip";
filePath = UPLOAD_PATH + zipName;
try {
// 初始化壓縮文件輸出流
out = new ZipOutputStream(new FileOutputStream(filePath));
// 清空輸出流(在迅雷下載不會出現一長竄)
response.reset();
//設置響應頭和客戶端保存文件名
response.setCharacterEncoding("utf-8");
response.setContentType("multipart/form-data");
// !!!new String(zipName.getBytes("GBK"), "8859_1") 如果文件包含中文,必須進行轉換,否則下載后的文件名是亂碼格式的
response.setHeader("Content-Disposition", "attachment;fileName=" + new String(zipName.getBytes("GBK"), "8859_1"));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 描述: 壓縮處理
* 參數: @param downloadFiles 批量下載的文件數據集合
*/
private void writeZip(List<UploadFileInfo> downloadFiles) {
byte[] buf = new byte[2048];
int len = 0;
try {
for (UploadFileInfo fileInfo : downloadFiles) {
// 獲取上傳文件
File file = new File(UPLOAD_PATH.substring(0, UPLOAD_PATH.lastIndexOf("upload")) + fileInfo.getFilePath());
if (!file.isFile()) {
continue;
}
// 設置編碼
out.setEncoding(System.getProperty("sun.jnu.encoding"));
// 設置壓縮文件名稱
ZipEntry ze = new ZipEntry(fileInfo.getFileName());
// 加入到輸出流中
out.putNextEntry(ze);
// 對源文件進行讀取並輸出
FileInputStream fis = new FileInputStream(file);
while ((len = fis.read(buf)) != -1) {
out.write(buf, 0, len);
}
// 刷新(必須要有)
out.flush();
out.closeEntry();
fis.close();
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 描述: 下載臨時壓縮文件
* 參數: @param response
*/
private void downFile(HttpServletResponse response) {
try {
File file = new File(filePath);
if (file.exists()) {
InputStream ins = new FileInputStream(filePath);
// 放到緩沖流里面
BufferedInputStream bins = new BufferedInputStream(ins);
// 獲取文件輸出IO流
OutputStream outs = response.getOutputStream();
BufferedOutputStream bouts = new BufferedOutputStream(outs);
int bytesRead = 0;
byte[] buffer = new byte[1024];
// 開始向網絡傳輸文件流
while ((bytesRead = bins.read(buffer)) != -1) {
bouts.write(buffer, 0, bytesRead);
}
// 這里一定要調用flush()方法
bouts.flush();
ins.close();
bins.close();
outs.close();
bouts.close();
}
} catch (IOException e) {
logger.error("文件下載出錯", e);
}
}
/**
* 描述: 刪除臨時壓縮文件
*/
private void afterProcess() {
// 刪除源文件
File tempZip=new File(filePath);
if(tempZip.exists()) {
tempZip.delete();
}
}
效果截圖:

詳細配置信息可以參考我寫的這篇文章:http://blog.ncmem.com/wordpress/2019/08/28/java%e6%89%b9%e9%87%8f%e4%b8%8b%e8%bd%bd/
