springboot 一键下载文件
依赖
<dependency><groupId>net.lingala.zip4j</groupId><artifactId>zip4j</artifactId><version>2.11.5</version></dependency>
具体实现
package com.transport.common.method.file;import com.transport.common.response.file.BatchDownloadFileResponse;
import com.transport.common.utils.DateUtils;
import com.transport.common.utils.file.FileUtils;
import lombok.extern.slf4j.Slf4j;
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.CompressionLevel;
import net.lingala.zip4j.model.enums.CompressionMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;/*** 批量将文件打包下载*/
@Slf4j
@Component
public class FileToZipUtil {/*** 创建 zip 文件** @param fileResponseList* @param tmpFileDirectory* @return*/public static BatchDownloadFileResponse createZipFile(List<BatchDownloadFileResponse> fileResponseList, String tmpFileDirectory) {String zipFileName = null;// 创建一个列表用于存放所有附件文件的路径,后续统一压缩到一个zip文件中String tempFileName = "";List<String> allFilePaths = new ArrayList<>();for (BatchDownloadFileResponse response : fileResponseList) {allFilePaths.add(response.getFilePath());String fileName = response.getFileName().substring(0, response.getFileName().lastIndexOf("."));tempFileName += fileName + "_";}tempFileName = tempFileName.substring(0, tempFileName.length() - 1);// 循环查询每个id对应的附件文件路径并添加到列表中// 里面的代码大家可能会觉得麻烦,不用细看,只需要知道这层for循环是为了找到附录文件在磁盘的地址String format = DateUtils.dateTimeNow();// 创建ZipFile对象,指定zip文件的路径tempFileName = format + tempFileName + ".zip";String cleanedFileName = cleanFileName(tempFileName);String tmpZipPath = tmpFileDirectory + File.separator + "tmpZip" + File.separator + cleanedFileName;// File tempFile = new File(tmpZipPath);
// if (!tempFile.exists()) {
// tempFile.mkdirs();
// }ZipFile zipFile = new ZipFile(tmpZipPath);zipFileName = tempFileName + ".zip";// 循环附录文件地址for (String filePath : allFilePaths) {File file = new File(filePath);if (file.exists()) {String folderNameInsideZip = tempFileName + "";// 构造在zip文件中存放的路径,格式为 "id标识的文件夹名/原文件名"try {// 尝试获取目标文件夹在zip文件中的FileHeaderFileHeader folderHeader = zipFile.getFileHeader(folderNameInsideZip + "/");
// log.info("文件夹在zip文件中的FileHeader:" + folderHeader);// 如果zip文件中指定目录不存在,则创建,这一步判断是必须的,不然会导致下一次文件添加动作会覆盖之前的文件if (Objects.isNull(folderHeader)) {new File(folderNameInsideZip).mkdirs(); // 创建文件夹ZipParameters folderPar = new ZipParameters();folderPar.setCompressionLevel(CompressionLevel.NORMAL);folderPar.setEncryptFiles(false);zipFile.addFolder(new File(folderNameInsideZip), folderPar);log.info("文件夹已成功添加到zip文件中。");}// 创建ZipParameters对象,用于设置添加文件的参数ZipParameters parameters = new ZipParameters();// 设置压缩方法,这里使用默认压缩方法parameters.setCompressionMethod(CompressionMethod.DEFLATE);// 设置压缩级别,这里使用默认压缩级别parameters.setCompressionLevel(CompressionLevel.NORMAL);// 设置添加文件在zip文件中的路径,格式为 "文件夹名/文件名"parameters.setFileNameInZip(folderNameInsideZip + "/" + file.getName());// 将文件添加到zip文件中的指定文件夹路径下zipFile.addFile(file, parameters);log.info("文件已成功添加到zip文件中的指定文件夹。");} catch (ZipException e) {e.printStackTrace();throw new RuntimeException(e);}}}String absolutePath = zipFile.getFile().getAbsolutePath();log.info("压缩包路径为 {}", zipFile.getFile().getAbsolutePath());BatchDownloadFileResponse batchDownloadFileResponse = new BatchDownloadFileResponse();batchDownloadFileResponse.setZipFileName(zipFileName);batchDownloadFileResponse.setZipFilePath(absolutePath);return batchDownloadFileResponse;}/*** 清理文件名中的特殊字符*/public static String cleanFileName(String fileName) {// 替换掉Windows系统不允许的特殊字符return fileName.replaceAll("[\\\\/:*?\"<>|& ]", "_");}
}
前端下载
systemDownLoadZipFile(fileData) {var url = baseURL + "/common/batchDownLoadFiles";axios({method: 'post',url: url,data: fileData,responseType: 'blob',headers: { 'Authorization': 'Bearer ' + getToken() }}).then((res) => {const isBlob = blobValidate(res.data);if (isBlob) {const blob = new Blob([res.data])this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))} else {this.printErrMsg(res.data);}})},
调用