java实现文件打包压缩下载接口(附上可实际运行的代码)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/fanrenxiang/article/details/95168890

最近在写项目接口,涉及到文件下载、打包压缩下载,单个文件下载还是比较简单的,多文件下载涉及到打包和压缩知识,之前也没做过,写篇博客做个简单的记录一下。闲言少叙,上代码:

如下代码是精简过后的测试代码,亲测可实际使用:

/**
 * @author simons.fan
 * @version 1.0
 * @date 2019/7/9
 * @description 文件下载controller
 **/
@RestController
@RequestMapping("/file")
public class FileController {

    private static final Logger logger = LoggerFactory.getLogger(FileController.class);

    @Autowired
    private DownLoadService downLoadService;

    /**
     * 单个文件下载
     *
     * @param fileName 真实存在的文件名
     */
    @GetMapping("/down-one")
    public void downOneFile(@RequestParam(value = "filename", required = false) String fileName) {
        logger.info("单个文件下载接口入参:[filename={}]", fileName);
        if (fileName.isEmpty()) {
            return;
        }
        try {
            downLoadService.downOneFile(fileName);
        } catch (Exception e) {
            logger.error("单个文件下载接口异常:{fileName={},ex={}}", fileName, e);
        }
    }

    /**
     * 批量打包下载文件
     *
     * @param fileName 文件名,多个用英文逗号分隔
     */
    @GetMapping("/down-together")
    public void downTogether(@RequestParam(value = "filename", required = false) String fileName) {
        logger.info("批量打包文件下载接口入参:[filename={}]", fileName);
        if (fileName.isEmpty()) return;
        List<String> fileNameList = Arrays.asList(fileName.split(","));
        if (CollectionUtils.isEmpty(fileNameList)) return;
        try {
            downLoadService.downTogetherAndZip(fileNameList);
        } catch (Exception e) {
            logger.error("批量打包文件下载接口异常:{fileName={},ex={}}", fileName, e);
        }
    }
}
/**
 * @author simons.fan
 * @version 1.0
 * @date 2019/7/9
 * @description 文件下载service
 **/
@Service
public class DownLoadServiceImpl implements DownLoadService {

    private static final Logger logger = LoggerFactory.getLogger(DownLoadServiceImpl.class);

    @Value("${file.path}")
    private String FILE_ROOT_PATH;

    /**
     * 单个文件下载
     *
     * @param fileName 单个文件名
     * @throws Exception
     */
    @Override
    public void downOneFile(String fileName) throws Exception {
        HttpServletResponse resp = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        File file = new File(FILE_ROOT_PATH + fileName);
        if (file.exists()) {
            resp.setContentType("application/x-msdownload");
            resp.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes(), "ISO-8859-1"));
            InputStream inputStream = new FileInputStream(file);
            ServletOutputStream ouputStream = resp.getOutputStream();
            byte b[] = new byte[1024];
            int n;
            while ((n = inputStream.read(b)) != -1) {
                ouputStream.write(b, 0, n);
            }
            ouputStream.close();
            inputStream.close();
        }
    }

    /**
     * 文件批量打包下载
     *
     * @param fileNameList 多个文件名,用英文逗号分隔开
     * @throws IOException
     */
    @Override
    public void downTogetherAndZip(List<String> fileNameList) throws IOException {
        HttpServletResponse resp = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        resp.setContentType("application/x-msdownload");
        //暂时设定压缩下载后的文件名字为test.zip
        resp.setHeader("Content-Disposition", "attachment;filename=test.zip");
        String str = "";
        String rt = "\r\n";
        ZipOutputStream zos = new ZipOutputStream(resp.getOutputStream());
        for (String filename : fileNameList) {
            str += filename + rt;
            File file = new File(FILE_ROOT_PATH + filename);
            zos.putNextEntry(new ZipEntry(filename));
            FileInputStream fis = new FileInputStream(file);
            byte b[] = new byte[1024];
            int n = 0;
            while ((n = fis.read(b)) != -1) {
                zos.write(b, 0, n);
            }
            zos.flush();
            fis.close();
        }
        //设置解压文件后的注释内容
        zos.setComment("download success:" + rt + str);
        zos.flush();
        zos.close();
    }
}

跑起来,测试,ok~

题外话

我们项目使用的是阿里云的OSS文件服务器,用过的小伙伴会发现,从OSS服务器返回的的是一个"OSSObject"对象,通过OSSObject对象,只能拿到对应的InputStream流,当时刚开始做,想法是直接将这个InputStream流写入到ZipOutputStream,一直不行。折腾半天,决定将这个InputStream流临时写入到运行服务的linux服务器,再来读这个file,当把这个文件写入到压缩对象类ZipOutputStream后,直接删除这个file即可,顺利解决我的问题。


引申阅读:

Java 导入导出功能总结:https://blog.csdn.net/fanrenxiang/article/details/80985879
记录一次mysql导入导出数据过程:https://blog.csdn.net/fanrenxiang/article/details/91491778

猜你喜欢

转载自blog.csdn.net/fanrenxiang/article/details/95168890