java压缩包加密上传,解密下载

业务场景

供应商上传投标文件需要进行加密处理,通过链接下载时下载的时加密的文件,而通过系统内访问接口下载时,下载的是解密好的文件。

问题解决思路

1. 首先配置三个保存文件的地址:上传地址,解密地址,再次加密地址(也就是最终地址)

2. 压缩包加密上传思路:上传压缩文件时,首先上传到上传地址进行解压,解压完成后,删除掉上传地址的压缩文件,生成密码保存数据库再次加密压缩到加密地址,并删除掉解压的文件。

3. 压缩包解密下载思路:通过系统外部链接下载时下载的是已经加密好的文件。而通过内部接口下载走解密接口,通过传入的信息,匹配数据库中响应的密码。进行解密并并再次进行无密码压缩。最终返回给用户解密后的压缩文件。

4. 使用工具:zip4j

核心方法

1. 引入依赖

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

2. 配置文件上传路径(在yml中配置并在需要使用的类中引入)

/*文件上传路径*/
    @Value(value = "${jeecg.path.upload}")
    private String uploadpath;
    /*压缩包解压路径*/
    @Value(value = "${jeecg.path.zipUpFile}")
    private String zipUpFile;
    /*压缩包上传路径*/
    @Value(value = "${jeecg.path.zipFilePath}")
    private String zipFilePath;

3. 加密压缩方法(封装到工具类中)

/**
     * 加密压缩
     */
    public void zipFolderToZip(String extractPath, String filePath, String password) throws Exception {
        try {
            log.debug("将" + extractPath + "目录下的文件打包并加密");
            String path = filePath.substring(0,filePath.lastIndexOf("/"));
            File destFile = new File(path);//压缩目录
            System.out.println(destFile.isDirectory());
            System.out.println(destFile.exists());
            destFile.mkdirs();
            if (!destFile.isDirectory() && !destFile.exists()) {
                destFile.mkdirs();
            }
            ZipFile zipFile = new ZipFile(filePath);
            ZipParameters parameters = new ZipParameters();
            parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
            parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
            if(password != null){
                //是否加密
                parameters.setEncryptFiles(true);
                //使用标准加密方式
                parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD);
                //设置加密密钥
                parameters.setPassword(password);
            }
            parameters.setIncludeRootFolder(false);

            zipFile.addFolder(extractPath, parameters);
            log.debug("将" + extractPath + "目录下的文件打包并加密 成功");

        } catch (ZipException e) {
            throw new Exception(e.getMessage());
        }

    }

4. 解密方法(封装到工具类中)

/**
     * 解压
     */
    public void upzip(File zipFile, String dest, String password) throws Exception {
        try {
            ZipFile zFile = new ZipFile(zipFile);//指向压缩文件.zip
            //设置文件名编码,在gbk系统中需要设置,文件名称是中文就不会乱码
//            zFile.setFileNameCharset("GBK");
            if (!zFile.isValidZipFile()) {// 检查文件是否合法
                throw new Exception("文件名不合法");
            }
            File destFile = new File(dest);//解压目录
            if (destFile.isDirectory() && !destFile.exists()) {
                destFile.mkdirs();
            }
            if (zFile.isEncrypted()) {//如果设置了密码
                zFile.setPassword(password.toCharArray());
            }
            zFile.extractAll(dest);//将文件输出到目标目录

        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
    }

2. 加密上传

ZipEncryptUtil zipEncryptUtil = new ZipEncryptUtil();
                File file = new File(ctxPath+File.separator+dbpath);
                String upPath = zipUpFile+"/"+dbpath;
                //将文件解压到该路径下
                zipEncryptUtil.upzip(file,upPath,null);
                //将文件打包到该路径
                String filePath = uploadpath+"/"+dbpath;
                zipEncryptUtil.zipFolderToZip(upPath,filePath,password);
                //删除上传的压缩文件
                zipEncryptUtil.deleteAnyone(ctxPath+"/"+dbpath);
                //删除解压后的文件
                zipEncryptUtil.deleteAnyone(upPath);

3. 解密下载

//获取解压文件路径
            String filePath = uploadpath + File.separator + imgPath;
            String downloadFilePath = uploadpath + File.separator + filePath;

            //将文件解压到指定路径
            File upFile = new File(filePath);
            String upPath = zipUpFile+"/"+imgPath;
            zipEncryptUtil.upzip(upFile,upPath,businessBidDoc.getFilePassword());

            //将文件压缩不加密压缩到指定路径
            String finalPath = zipFilePath+"/"+imgPath;
            zipEncryptUtil.zipFolderToZip(upPath,finalPath,null);

            File file = new File(downloadFilePath);

            response.setContentType("application/force-download");// 设置强制下载不打开
            response.addHeader("Content-Disposition", "attachment;fileName=" + new String(file.getName().getBytes("UTF-8"),"iso-8859-1"));
            inputStream = new BufferedInputStream(new FileInputStream(finalPath));
            outputStream = response.getOutputStream();
            byte[] buf = new byte[1024];
            int len;
            while ((len = inputStream.read(buf)) > 0) {
                outputStream.write(buf, 0, len);
            }
            response.flushBuffer();
            //删除解压的压缩文件
            zipEncryptUtil.deleteAnyone(upPath);
            //删除解压后重新压缩的文件
            zipEncryptUtil.deleteAnyone(finalPath);