多文件下载到压缩包

发布时间 2023-05-31 15:35:27作者: 睡个好觉"

    /**
     * 多个图片下载到zip
     */
    private void multiDownload(List<DownloadFileReqVo> fileReqVoList, HttpServletResponse resp) throws BaseAppException {
        try {
            // 创建临时文件
            File zipFile = File.createTempFile("downloadImage4Wms", ".zip");
            // 生成文件
            buildZipFile(fileReqVoList, resp, zipFile);
        } catch (IOException e) {
            log.error("tempFile create failed, msg: " + e.getMessage(), e);
        }
    }

    /**
     * 生成文件
     */
    private void buildZipFile(List<DownloadFileReqVo> fileReqVoList, HttpServletResponse resp, File zipFile) throws BaseAppException {
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        OSSClient ossClient = null;
        try (FileOutputStream fos = new FileOutputStream(zipFile);
             // 为任何OutputStream产生校验,第一个参数是制定产生校验和的输出流,第二个参数是指定Checksum的类型 (Adler32(较快)和CRC32两种)
             CheckedOutputStream cos = new CheckedOutputStream(fos, new Adler32());
             // 用于将数据压缩成Zip文件格式
             ZipOutputStream zos = new ZipOutputStream(cos);
        ) {
            ossClient = new OSSClient(OssConfig.OSS_END_POINT, OssConfig.OSS_ACCESS_KEY_ID, OssConfig.OSS_ACCESS_KEY_SECRET);
            // key:文件名称,value:重复个数
            Map<String, Integer> nameMap = new HashMap<>();
            // 生成zip中的文件
            buildFile(fileReqVoList, zos, ossClient, nameMap);
            zos.close();
            String fileName = URLEncoder.encode(FHHD_NAME, Constants.ENCODING_UTF8);
            // 文件名称结尾增加时间
            String dateNow = DateUtils.date2String(DateUtils.getNowDate(), DateUtils.DATE_FORMAT_NOSPLIT);
            fileName = fileName + dateNow + ".zip";
            // 清除首部的空白行
            resp.reset();
            resp.setContentType("application/octet-stream; charset=utf-8");
            resp.setHeader("Location", fileName);
            resp.setHeader("Cache-Control", "max-age=0");
            resp.setHeader("Content-Disposition", "attachment; filename=" + fileName);

            fis = new FileInputStream(zipFile);
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(resp.getOutputStream());
            byte[] buffer = new byte[1024];
            int l = 0;
            while (l < zipFile.length()) {
                int j = bis.read(buffer, 0, 1024);
                l += j;
                bos.write(buffer, 0, j);
            }
        } catch (Exception e) {
            log.error("multifile download4OssPri failed, msg: " + e.getMessage(), e);
            throw new BaseAppException("multifile download4OssPri failed, msg: " + e.getMessage(), e);
        } finally {
            if (null != ossClient) {
                ossClient.shutdown();
            }
            // 关闭流
            IOUtils.closeQuietly(fis, bis, bos);
            try {
                // 删除临时文件
                Files.delete(zipFile.toPath());
            } catch (IOException e) {
                log.error("tempFile delete failed, msg: " + e.getMessage(), e);
            }
        }
    }

    /**
     * 生成zip中的文件
     */
    private void buildFile(List<DownloadFileReqVo> fileReqVoList, ZipOutputStream zos, OSSClient ossClient, Map<String, Integer> nameMap) throws IOException {
        for (DownloadFileReqVo fileReqVo : fileReqVoList) {
            // 获取Object,返回结果为OSSObject对象
            OSSObject ossObject = ossClient.getObject(OssConfig.OSS_PRI_BUCKET_NAME, fileReqVo.getDopFilePath());
            // 读取Object内容 返回
            InputStream inputStream = ossObject.getObjectContent();
            // 对于每一个要被存放到压缩包的文件,都必须调用ZipOutputStream对象的putNextEntry()方法,确保压缩包里面文件不同名
            String name = fileReqVo.getDopFileName();
            // 如果文件名重复,则将文件名后缀加1
            if (Utils.notEmpty(nameMap.get(name))) {
                nameMap.put(name, nameMap.get(name) + 1);
                name = name.substring(0, name.lastIndexOf(".")) + " ("+ nameMap.get(name) +")" + name.substring(name.lastIndexOf("."));
            } else {
                nameMap.put(name, 0);
            }
            zos.putNextEntry(new ZipEntry(name));
            int bytesRead = 0;
            // 向压缩文件中输出数据
            while ((bytesRead = inputStream.read()) != -1) {
                zos.write(bytesRead);
            }
            inputStream.close();
            // 当前文件写完,定位为写入下一条项目
            zos.closeEntry();
        }
    }