Java实现多文件边压缩边下载

Java实现多文件边压缩边下载

 //照片存放路径
  @Value("${img.url:D:/download/image/}")
  private String imgUrl;
  
  @Value("${img.suffix:.jpg}")
  private String imgSuffix;

  @Value("${csv.url:D:/download/csv/}")

public void exportEmployee(HttpServletRequest request,
      HttpServletResponse response, String employeeId) {

    String[] employeeIds = employeeId.split(",");

    //判断文件夹是否存在
    if (!FileUtil.exist(csvUrl)) {
      //创建文件夹
      FileUtil.mkdir(csvUrl);
    }

    //查询
    List<EmployeeDto> dtoList = employeeService.findEmployeeInId(employeeIds);
    //存储照片
    List<File> fileList = new ArrayList<>();
    //写入cvs
    List<String[]> csvList = new ArrayList();
    //表头
    String[] headArr = new String[]{"人员编号", "证件类型", "人员类型", "姓名", "性别", "出生日期", "权限组名称", "卡号",
        "卡号有效时间", "部门", "国家", "省份", "城市", "人脸图片1", "特征值1", "人脸图片2", "特征值2", "人脸图片3", "特征值3"};
    csvList.add(headArr);
    String[] bodyArr;

    for (EmployeeDto l : dtoList) {

      //照片存储路径  imgUrl+部门+名字+imgSuffix
      String photoUrl = imgUrl + l.getDepartmentName() + "/";

      //判断文件夹是否存在
      if (!FileUtil.exist(photoUrl)) {
        //创建文件夹
        FileUtil.mkdir(photoUrl);
      }

      //判断照片是否存在
      if (!FileUtil.isDirectory(photoUrl + l.getEmployeeName() + imgSuffix)) {
        if (!ImageBase64Utils
            .saveToImgByStr(l.getPhoto(), photoUrl, l.getEmployeeName() + imgSuffix)) {
          log.error("{}图片保存本地失败", l.getPhoto());
          return;
        }
      }

      //添加照片文件
      fileList.add(new File(photoUrl + l.getEmployeeName() + imgSuffix));
      bodyArr = new String[headArr.length];
      //人员编号
      bodyArr[0] = l.getEmployeeId();
      //姓名
      bodyArr[3] = l.getEmployeeName();
      //性别
      bodyArr[4] = l.getSexId().equals(1) ? "男" : "女";
      //出生日期
      bodyArr[5] = DateUtil.format(l.getBirthday(), "yyyy-MM-dd");
      //卡号有效时间
      bodyArr[8] = "2000/01/01-2037/12/31";
      //部门
      bodyArr[9] = l.getLayerorder().replaceAll("-", "/");
      //人脸图片1
      bodyArr[13] = l.getEmployeeName() + imgSuffix;
      csvList.add(bodyArr);
    }
    download(csvList,request,response,fileList);
  }

  /**
   * 功能描述  创建csv文件,删除csv文件,创建zip,导出
   *
   * @param csvList 学员信息
   * @param request HttpServletRequest
   * @param response HttpServletResponse
   * @param fileList 文件列表
   * @return void
   * @author yz
   * @date 2019-08-28
   */
  public void download(List<String[]> csvList, HttpServletRequest request,
      HttpServletResponse response, List<File> fileList) {
    String csvName =
        "PersonnelInformation-" + DateUtil.format(new Date(), "yyyyMMddhhmmsss") + ".csv";

    //指定路径和编码 生成CSV
    // CSV文件本身为一种简单文本格式,有编码区分。Excel读取CSV文件中含有中文时时必须为GBK编码(Windows平台下),否则会出现乱码。
    CsvWriter writer = CsvUtil.getWriter(csvUrl + csvName, CharsetUtil.CHARSET_GBK);
    //按行写出
    writer.write(csvList);
    //关闭写入
    writer.close();
    //响应头的设置
    response.reset();
    response.setCharacterEncoding("utf-8");
    response.setContentType("multipart/form-data");

    //创建csv文件
    File csvFile = new File(csvUrl + csvName);
    if (null == csvFile) {
      log.error("csv文件不存在");
      return;
    }
    //添加到压缩列表
    fileList.add(csvFile);

    //设置压缩包的名字
    //解决不同浏览器压缩包名字含有中文时乱码的问题
    String downloadName =
        "PersonnelInformation-" + DateUtil.format(new Date(), "yyyyMMddhhmmsss") + ".zip";
    String agent = request.getHeader("USER-AGENT");
    try {
      if (agent.contains("MSIE") || agent.contains("Trident")) {
        downloadName = java.net.URLEncoder.encode(downloadName, "UTF-8");
      } else {
        downloadName = new String(downloadName.getBytes("UTF-8"), "ISO-8859-1");
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    response.setHeader("Content-Disposition", "attachment;fileName=\"" + downloadName + "\"");

    //设置压缩流:直接写入response,实现边压缩边下载
    ZipOutputStream zipos = null;
    try {
      zipos = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
      //设置压缩方法
      zipos.setMethod(ZipOutputStream.DEFLATED);
    } catch (Exception e) {
      log.error("设置压缩流出现异常" + e.getMessage());
      e.printStackTrace();
    }

    //循环将文件写入压缩流
    DataOutputStream os = null;
    for (int i = 0; i < fileList.size(); i++) {

      File file = fileList.get(i);
      try {
        //添加ZipEntry,并ZipEntry中写入文件流
        //这里,加上i是防止要下载的文件有重名的导致下载失败
        zipos.putNextEntry(new ZipEntry(file.getName()));
        os = new DataOutputStream(zipos);
        InputStream is = new FileInputStream(file);
        byte[] b = new byte[100];
        int length;
        while ((length = is.read(b)) != -1) {
          os.write(b, 0, length);
        }
        is.close();
        zipos.closeEntry();
      } catch (IOException e) {
        log.error("循环将文件写入压缩流出现异常" + e.getMessage());
        e.printStackTrace();
      }
    }

    //关闭流
    try {
      os.flush();
      os.close();
      zipos.close();
    } catch (IOException e) {
      log.error("关闭流现异常" + e.getMessage());
      e.printStackTrace();
    }

    //删除生成的csv
    if (!FileUtil.del(csvUrl + csvName)) {
      log.error("删除{}文件失败", csvName);
    }
  }

  /**
   * 功能描述 二进制转base64
   *
   * @param dtoList 查询出来的数据列表
   * @return java.util.List<com.yczn.dto.EmployeeDto>
   * @author yz
   * @date 2019-08-27
   */
  private List<EmployeeDto> imgToString(List<EmployeeDto> dtoList) {
    for (EmployeeDto employeeDto : dtoList) {

      Encoder encoder = Base64.getEncoder();

      employeeDto.setPhotoBase64(
          employeeDto.getPhoto() != null ? encoder.encodeToString(employeeDto.getPhoto()) : "");
    }
    return dtoList;
  }