Java-文档文件下载(保持目录结构的zip包下载)

最近项目中遇到关于客户档案管理的需求,其中的下载需求如下:
1. 单个文件直接下载,多个文件下载自动打zip包。
2. 下载的zip包中保留指定的目录结构(目录结构自定义)

后端代码分享如下:
 

1. controller层:

    @PostMapping("/download")
    public void downLoadFile(DownloadParams downloadParams, HttpServletResponse response) {
        //多个文件下载url,用 ,分隔的
        logger.info("下载文档url:{}", downloadParams.getFileKeys());
        if (StringUtils.isNotBlank(downloadParams.getFileKeys())) {
            List fileKeys = new ArrayList<>(Arrays.asList(downloadParams.getFileKeys().split(",")));
            response.setContentType("application/octet-stream;charset=utf-8");
            if (fileKeys.size() == 1) {
                String fileUrl = fileKeys.get(0);
                String[] arr = fileUrl.split("/");
                String fileName = arr[arr.length - 1].split("\\?")[0];
                response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
                try {
                    downloadService.downloadFile(fileUrl, response.getOutputStream());
                } catch (IOException e) {
                    logger.info("下载文档失败,e:{}", e);
                    throw new BadRequestAlertException("文件下载失败,请联系管理员!", "download", "error");
                }
            } else {
                //多文档下载,以zip包形式下载
                String zipFileName = System.currentTimeMillis()+".zip";
                response.setHeader("Content-Disposition", "attachment;filename=" + zipFileName);
                try {
                    downloadService.downloadZipPackage(fileKeys, response.getOutputStream());
                } catch (IOException e) {
                    logger.error("批量下载客户文档出错 error:{}", e);
                    throw new BadRequestAlertException("批量下载异常,请联系管理员!", "", "error");
                }
            }
        } else {
            throw new BadRequestAlertException("未选择任何待下载文件,请先勾选待下载文件!", "", "error");
        }
    }

2. DownloadServiceImpl的代码:
 

@Service
public class DownLoadServiceImpl implements DownloadService {
    private final Logger logger = LoggerFactory.getLogger(BussinessInfoServiceImpl.class);

    @Override
    public void downloadFile(String fileUrl, OutputStream out) {
        URLConnection conn = null;
        try {
            URL url = new URL(fileUrl);
            conn = url.openConnection();
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        if (conn != null) {
            try (InputStream inStream = conn.getInputStream()) {
                int len;
                byte[] buffer = new byte[1024];
                while ((len = inStream.read(buffer)) != -1) {
                    out.write(buffer, 0, len);
                }
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }
        }
    }

    @Override
    public void downloadZipPackage(List fileUrls, OutputStream out) throws IOException {
        //将输出流转换成Zip输出流
        ZipOutputStream zos = new ZipOutputStream(out);
        List fileNames = new ArrayList<>();
        for (String fileUrl : fileUrls) {
            //根据Url获取文件名
            String[] arr = fileUrl.split("/");
            String fileName = arr[arr.length - 1].split("\\?")[0];
            if (fileNames.contains(fileName)) {
                //如果文件有重名,会自动修改文件名,防止打包出错
                fileName = System.currentTimeMillis() + fileName;
            }
            fileNames.add(fileName);
            //这里的目录结构只是举例,可以是任何目录,相同目录前缀的文件将会被放在一起,不同的就会分开存放
            StringBuilder dirName = new StringBuilder("一级目录/").append("二级目录/").append("三级目录");
            fileName = dirName.toString() + File.separator + fileName;
            URL url = new URL(fileUrl);
            zos.putNextEntry(new ZipEntry(fileName));
            URLConnection httpConn = url.openConnection();
            //获取文件的网络输入流
            InputStream fis = httpConn.getInputStream();
            byte[] buffer = new byte[1024];
            int r;
            while ((r = fis.read(buffer)) != -1) {
                zos.write(buffer, 0, r);
            }
            fis.close();
        }
        zos.flush();
        zos.close();
    }
}

功力有限,代码有写的不好的地方,欢迎大家指教!

你可能感兴趣的:(java)