java批量下载mongodb文件并将其压缩为zip文件,通过流从浏览器中下载该zip文件

先说全局,整体思想就是将mongodb中的文件循环取出并生成独立文件,将路径存入队列,处理完mongdb中的文件路径后,在方法末尾激活批量处理压缩文件的方法,将队列传给该方法,让其循环调用压缩方法将每个文件压缩进zip文件中,并将zip文件生成实体文件,待其以二进制流的形式传给浏览器后,删除本地zip压缩文件及mongodb中下载的各个文件。
Controller层写法

/**
   * mongodb批量下载文件,并打成zip压缩包
   *
   * @param params id数组
   * @param request 请求
   * @param response 返回
   */
  @PostMapping("/downloadZip")
  @ApiLogAnnotation(
      interfaceTypeCode = "downloadZip",
      interfaceDescription = "mongodb批量下载文件,并打成zip压缩包")
  public void downloadZipByMongodb(
      @RequestBody Map<String, Object> params,
      HttpServletRequest request,
      HttpServletResponse response) {
    try {
      downloadMongodbService.downloadZipByMongodb(params, request, response);
    } catch (Exception e) {
      e.printStackTrace();
      log.info("mongodb批量下载文件,并打成zip压缩包失败!");
    }
  }

service层写法

  /**
   * 批量下载并压缩
   *
   * @param params id数组
   * @param request 请求
   * @param response 返回
   * @throws IOException io流异常
   */
  void downloadZipByMongodb(
      Map<String, Object> params, HttpServletRequest request, HttpServletResponse response)
      throws Exception;
}

Impl层写法

@Override
  public void downloadZipByMongodb(
      Map<String, Object> params, HttpServletRequest request, HttpServletResponse response)
      throws Exception {
    String ids = Optional.ofNullable(params).map(p -> p.get("ids")).orElse("").toString();
    if (StringUtil.isBlank(ids)) {
      response.setHeader("Content-Disposition", "");
    } else {
      List<String> paths = new ArrayList<>();
      String filePath = request.getSession().getServletContext().getRealPath("");
      String[] idList = ids.split(",");
      /*	循环从mongodb下载文件*/
      for (String id : idList) {
        Query query = Query.query(Criteria.where("_id").is(id));
        // 查询单个文件
        GridFSFile gfsFile = gridFsTemplate.findOne(query);
        if (gfsFile != null) {
          GridFsResource gridFsResource =
              new GridFsResource(
                  gfsFile,
                  GridFSBuckets.create(mongoDbFactory.getMongoDatabase())
                      .openDownloadStream(gfsFile.getObjectId()));
          String fileName = gfsFile.getFilename().replace(",", "");
          // 处理中文文件名乱码
          if (request.getHeader("User-Agent").toUpperCase().contains("MSIE")
              || request.getHeader("User-Agent").toUpperCase().contains("TRIDENT")
              || request.getHeader("User-Agent").toUpperCase().contains("EDGE")) {
            fileName = java.net.URLEncoder.encode(fileName, "UTF-8");
          } else {
            // 非IE浏览器的处理:
            fileName = new String(fileName.getBytes(), StandardCharsets.UTF_8);
          }
          String newfilePath = filePath + File.separator + fileName;
          paths.add(newfilePath);
          File file = new File(newfilePath);
          copyInputStreamToFile(gridFsResource.getInputStream(), file);
        }
      }
      plistDownLoad(paths, request, response);
    }
  }
   /** 将GridFsResource转成File */
  private static void copyInputStreamToFile(InputStream inputStream, File file) throws IOException {
    try (FileOutputStream outputStream = new FileOutputStream(file)) {
      int read;
      byte[] bytes = new byte[1024];
      while ((read = inputStream.read(bytes)) != -1) {
        outputStream.write(bytes, 0, read);
      }
    }
  }
 /** 批量压缩并下载 */
  public void plistDownLoad(
      List<String> paths, HttpServletRequest request, HttpServletResponse response)
      throws Exception {
    String filePath = request.getSession().getServletContext().getRealPath("");
    if (paths.size() != 0) {
      // 创建临时路径,存放压缩文件
      String zipFilePath = filePath + File.separator + "我的zip.zip";
      // 压缩输出流,包装流,将临时文件输出流包装成压缩流,将所有文件输出到这里,打成zip包
      ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(Paths.get(zipFilePath)));
      // 循环调用压缩文件方法,将一个一个需要下载的文件打入压缩文件包
      for (String path : paths) {
        // 该方法在下面定义
        fileToZip(path, zipOut);
      }
      // 压缩完成后,关闭压缩流
      zipOut.close();
      // 拼接下载默认名称并转为ISO-8859-1格式
      String fileName = new String(("我的压缩文件.zip").getBytes(), StandardCharsets.UTF_8);
      response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
      // 该流不可以手动关闭,手动关闭下载会出问题,下载完成后会自动关闭
      ServletOutputStream outputStream = response.getOutputStream();
      FileInputStream inputStream = new FileInputStream(zipFilePath);
      // 如果是SpringBoot框架,在这个路径
      // org.apache.tomcat.util.http.fileupload.IOUtils产品
      // 否则需要自主引入apache的 commons-io依赖
      // copy方法为文件复制,在这里直接实现了下载效果
      IOUtils.copy(inputStream, outputStream);
      // 关闭输入流
      inputStream.close();
      // 下载完成之后,删掉这个zip包
      File fileTempZip = new File(zipFilePath);
      fileTempZip.delete();
      /*循环删除mongodb的文件*/
      for (String path : paths) {
        File file = new File(path);
        file.delete();
      }
    }
  }
   /** 单个文件压缩进zip文件 */
  public static void fileToZip(String filePath, ZipOutputStream zipOut) throws IOException {
    // 需要压缩的文件
    File file = new File(filePath);
    // 获取文件名称,如果有特殊命名需求,可以将参数列表拓展,传fileName
    String fileName = file.getName();
    FileInputStream fileInput = new FileInputStream(filePath);
    // 缓冲
    byte[] bufferArea = new byte[1024 * 10];
    BufferedInputStream bufferStream = new BufferedInputStream(fileInput, 1024 * 10);
    // 将当前文件作为一个zip实体写入压缩流,fileName代表压缩文件中的文件名称
    zipOut.putNextEntry(new ZipEntry(fileName));
    int length = 0;
    // 最常规IO操作,不必紧张
    while ((length = bufferStream.read(bufferArea, 0, 1024 * 10)) != -1) {
      zipOut.write(bufferArea, 0, length);
    }
    // 关闭流
    fileInput.close();
    // 需要注意的是缓冲流必须关闭掉,否则输出无效
    bufferStream.close();
    // 压缩流不必关闭,使用完后再关
  }
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值