问题场景

在日常开发中, 数据导出遇到的情况不少, 但是基本都是单个文件导出. 本次项目开发中遇到需要批量导出的情况, 查找资料后功能基本实现, 先记录一下.

解决代码

  1. public void getFile(String fileName, String time, HttpServletResponse response) {
  2. response.setContentType("application/octet-stream");
  3. response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".zip");
  4. byte[] buff = new byte[1024];
  5. // 创建缓冲输入流
  6. OutputStream outputStream = null;
  7. List<SysTempFilePo> pos = tempFileService.list(new QueryWrapper<SysTempFilePo>().eq("time", time));
  8. Assert.notEmpty(pos, "服务器找不到上传的文本内容, 请重试");
  9. try {
  10. // 创建ByteArrayOutputStream 存储压缩流,后期用于读出压缩文件流内容
  11. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  12. // 创建ZipOutputStream 用于生成压缩文件流
  13. ZipOutputStream zos = new ZipOutputStream(bos);
  14. for (SysTempFilePo po : pos) {
  15. String html = po.getHtml();
  16. String css = po.getCss();
  17. String name = po.getName();
  18. // 创建压缩文件内容实例
  19. // 如果需要创建多个可多次putNextEntry
  20. zos.putNextEntry(new ZipEntry("/" + name + "/" + name + ".vue"));
  21. // 读取文件内容,并将文件内容放到压缩流中
  22. zos.write(html.getBytes(Charsets.UTF_8));
  23. zos.putNextEntry(new ZipEntry("/" + name + "/" + name + ".css"));
  24. zos.write(css.getBytes(Charsets.UTF_8));
  25. }
  26. // 切记要先关闭流,不然后续无法获取压缩流内容
  27. zos.close();
  28. // 获取压缩字节流
  29. byte[] zipBytes = bos.toByteArray();
  30. outputStream = response.getOutputStream();
  31. outputStream.write(zipBytes);
  32. outputStream.flush();
  33. } catch (IOException e) {
  34. // 出现异常返回给页面失败的信息
  35. log.error(e.getMessage(), e);
  36. } finally {
  37. if (outputStream != null) {
  38. try {
  39. outputStream.close();
  40. } catch (IOException e) {
  41. log.error(e.getMessage(), e);
  42. }
  43. }
  44. }

测试结果

image.png

注意点

在使用压缩流写文件时候,如果需要展示文件层级关系或者指定文件夹, 可以在给文件命名时使用’/‘拼接即可. 如

  1. zos.putNextEntry(new ZipEntry("/" + name + "/" + name + ".css"))