【Zip】使用 SpringBoot 实现 zip文件的导入和导出

了解到有两种解压 zip 文件的方式:org.apache.tools.zip.ZipFile ;SpringBoot 自带的 net.lingala.zip4j.core.ZipFile。这里选择第二种。

引入 POM 依赖:

<dependency>
	<groupId>net.lingala.zip4j</groupId>
	<artifactId>zip4j</artifactId>
	<version>1.3.1</version>
</dependency>

1. Zip 文件导入

FileController 添加一个接口:

@PostMapping("/importZipFile")
public ResultVo<String> importZipFile(@RequestParam("zipFile") MultipartFile zipFile) {
    return fileService.importZipFile(zipFile);
}

FileServiceImpl

public ResultVo<String> importZipFile(MultipartFile zipFile) {
    // 1.校验入参
    ResultVo<String> resultVo = checkZipFileParam(zipFile);
    if (!resultVo.checkSuccess()) {
        return resultVo;
    }
    // 2.上传至服务器路径下
    ResultVo<String> uploadFileResultVo = uploadFile(zipFile);
    if (!uploadFileResultVo.checkSuccess()) {
        return uploadFileResultVo;
    }
    // 3.解压Zip文件
    String uploadZipFilePath = uploadFileResultVo.getData();
    boolean unPackZip = FileUtil.unPackZip(new File(uploadZipFilePath), "", FileUtil.getUploadZipPath(), true);
    if (!unPackZip) {
        return ResultVoUtil.error("【导入Zip文件】失败");
    }
    log.info("【导入Zip文件】成功");
    return ResultVoUtil.success("【导入Zip文件】成功");
}

checkZipFileParam():校验Zip文件的入参

public ResultVo<String> checkZipFileParam(MultipartFile zipFile) {
    if (Objects.isNull(zipFile)) {
        return ResultVoUtil.error("【导入Zip文件】缺少Zip包");
    }
    String contentType = zipFile.getContentType();
    if (!FileConstant.CONTENT_TYPE_ZIP.equals(contentType) && !FileConstant.CONTENT_TYPE_ZIP_COMPRESSED.equals(contentType)) {
        return ResultVoUtil.error("【导入Zip文件】上传的文件类型不是Zip");
    }
    return ResultVoUtil.success();
}

FileConstant:文件常量类

public interface FileConstant {

    // UTF-8 字符集
    String UTF8 = "UTF-8";

    // GBK
    String GBK = "GBK";

    // 文件类型 <application/zip>
    String CONTENT_TYPE_ZIP = "application/zip";

    // 文件类型 <application/x-zip-compressed>
    String CONTENT_TYPE_ZIP_COMPRESSED = "application/x-zip-compressed";

}

FileUtil.unPackZip():解压

public static boolean unPackZip(File zipFile, String password, String desPath, boolean isDel) {
    try {
        ZipFile zip = new ZipFile(zipFile);
        // 这里是windows系统上传,所以,就用 GBK 编码咯
        zip.setFileNameCharset(FileConstant.GBK);
        log.info("【文件解压】begin unpack zip file....");
        // 将文件输出到目标目录
        zip.extractAll(desPath);
        if (zip.isEncrypted()) {
            zip.setPassword(password);
        }
    } catch (ZipException e) {
        log.error("【文件解压】异常,路径:{} ,异常信息:{} ", desPath, e);
        return false;
    }
    if (isDel) {
        zipFile.deleteOnExit();
    }
    return true;
}

说明:

  1. 解压缩时,需要设置文件编码的类型。Linux/Mac 系统默认是 UTF-8windows 系统默认是 GBK
  2. deleteOnExit():在虚拟机终止时,请求删除此抽象路径名表示的文件或目录;delete() 方法:直接删除

getUploadZipPath():获取Zip文件上传路径

public static String getUploadZipPath() {
    return fileConfig.getUploadZipPath();
}

FileConfig:添加一个属性

public class FileConfig {

    // 上传路径
    private String uploadPath;

    // 下载路径
    private String downloadPath;

    // 上传Zip文件路径
    private String uploadZipPath;

}

application.yml

file:
  uploadPath: E:/upload
  downloadPath: E:/download
  uploadZipPath: E:/uploadZipPath

2. Zip 导出

FileController:添加一个Zip文件下载接口

@PostMapping("/exportZipFile")
public ResultVo exportZipFile(final HttpServletResponse response) {
    return fileService.exportZipFile(response);
}

FileServiceImpl:导出Zip文件

public ResultVo<String> exportZipFile(HttpServletResponse response) {
    // 1.根据条件找到要压缩的文件/目录或者自己生成文件/目录(这里写死)
    String srcPath = getSrcPathByCondition();
    // 2.压缩文件
    String desPath = FileUtil.packZip(srcPath, FileUtil.getDownloadZipPath(), false, null);
    if (StringUtil.isBlank(desPath)) {
        log.error("【文件压缩】压缩失败");
        return ResultVoUtil.error("【文件压缩】压缩失败");
    }
    log.info("【文件压缩】压缩成功,压缩文件路径为:{}", desPath);
    // 3.下载Zip文件
    ResultVo<String> downLoadZipResultVo = downloadFile(desPath, response);
    if (null != downLoadZipResultVo && !downLoadZipResultVo.checkSuccess()) {
        log.error("【导出Zip文件】下载文件失败");
        return downLoadZipResultVo;
    }
    // 4.删除Zip文件
    boolean deleteFile = FileUtil.deleteFile(new File(desPath));
    if (!deleteFile) {
        log.error("【下载Zip文件】删除临时文件失败,临时文件路径为{}", desPath);
        return ResultVoUtil.error("删除临时文件失败");
    }
    log.info("【下载Zip文件】删除临时文件成功,临时文件路径为:{}", desPath);
    return null;
    
}

getSrcPathByCondition():获取要压缩的源路径

// 获取要压缩的源路径
public String getSrcPathByCondition() {
    return "E:/upload/2021-11-11";
}

FileUtil.packZip():压缩Zip文件。对于给定的文件(夹)压缩到指定位置

public static String packZip(String srcPath, String desPath, boolean isCreateDir, String password) {
    File srcFile = new File(srcPath);
    desPath = buildDestinationZipFilePath(srcFile, desPath);
    ZipParameters parameters = new ZipParameters();
    // 压缩方式
    parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
    // 压缩级别
    parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
    if (!StringUtil.isBlank(password)) {
        parameters.setEncryptFiles(true);
        // 加密方式
        parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD);
        parameters.setPassword(password.toCharArray());
    }

    try {
        ZipFile zipFile = new ZipFile(desPath);
        log.info("【文件压缩】begin pack zip file....");
        if (srcFile.isDirectory()) {
            if (!isCreateDir) {
                // 如果不创建目录的话,将直接把源目录下的文件给压缩
                File[] subFiles = srcFile.listFiles();
                ArrayList<File> files = new ArrayList<>();
                Collections.addAll(files, subFiles);
                zipFile.addFiles(files, parameters);
            } else {
                zipFile.addFolder(srcFile, parameters);
            }
        } else {
            zipFile.addFile(srcFile, parameters);
        }
        return desPath;
    } catch (ZipException e) {
        log.error("【压缩ZiP文件】失败,失败信息为:{}", e);
        return null;
    }
}

buildDestinationZipFilePath():构建压缩文件存放路径

public static String buildDestinationZipFilePath(File srcFile,String destParam) {
    if (!StringUtil.isBlank(destParam) && destParam.endsWith(FileConstant.ZIP_FILE_SUFFIX)) {
        return destParam;
    }
    if (srcFile.isDirectory()) {
        destParam = srcFile.getParent() + File.separator + srcFile.getName() + FileConstant.ZIP_FILE_SUFFIX;
    } else {
        String fileName = srcFile.getName().substring(0, srcFile.getName().lastIndexOf("."));
        destParam = srcFile.getParent() + File.separator + fileName + FileConstant.ZIP_FILE_SUFFIX;
    }
    return destParam;
}

FileConstant

public interface FileConstant {

	...

    // 文件分隔符
    String FILE_SPLIT = "/";

}

FileConfig:

public class FileConfig {

    ...

    // 下载Zip文件路径
    private String downloadZipPath;

}

application.yml

file:
  uploadPath: E:/upload
  downloadPath: E:/download
  uploadZipPath: E:/uploadZipPath
  downloadZipPath: E:/downloadZipPath
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值