基于java实现zip文件上传至服务器

package com.research.business.controller;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ZipUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.research.common.annotation.Anonymous;
import com.research.common.core.domain.AjaxResult;
import com.research.common.core.domain.R;
import com.research.process.mapper.CityAndCountyMapper;
import com.research.process.mapper.PdfCodeMapper;
import com.research.process.service.CityAndCountyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**

  • 文件上传

  • @author zjl

  • @description TODO

  • @time: 2023/8/27 17:02
    */
    @Anonymous
    @RestController
    @RequestMapping("/uploadFile")
    public class FileUploadController {

    private static final Logger log = LoggerFactory.getLogger(FileUploadController.class);

    @Resource
    private PdfCodeMapper pdfCodeMapper;

    @Resource
    private CityAndCountyService cityAndCountyService;

    // 设置上传文件保存的目录
    @Value("${file.UPLOAD_DIR}")
    private String UPLOAD_DIR;

    @PostMapping("/upload")
    public AjaxResult multiFace(@RequestParam("file") MultipartFile file) {
    if (file.isEmpty()) {
    return AjaxResult.error("请选择要上传的压缩文件");
    } else if (!Objects.requireNonNull(file.getOriginalFilename()).toLowerCase().endsWith(".zip")) {
    log.error("不是有效的.zip文件");
    return AjaxResult.error("不是有效的.zip文件");
    }

     try {
         //获取文件全名
         String fileName = file.getOriginalFilename();
         log.info("上传的压缩包名称为:" + fileName);
    
         //解压目标文件夹对象(压缩文件解压到此文件夹中)
         File extractFolder = new File(UPLOAD_DIR);
    
         //压缩包存储目标文件对象
         File destFile = new File(UPLOAD_DIR + fileName);
    
         //文件上传路径对象
         File fileDirectory = new File(UPLOAD_DIR);
         log.info("上传的压缩包的保存路径为:" + fileDirectory);
    
         //当上传路径不存在时,生成上传路径
         if (!fileDirectory.exists()) {
             fileDirectory.mkdirs();
             log.info("压缩包的上传路径 " + fileDirectory + " 不存在,已创建");
         }
    
         //调用处理压缩包文件方法得到返回结果
         return dealZip(file, subName(file), destFile, extractFolder);
    
     } catch (Exception e) {
         e.printStackTrace();
         log.error("文件上传失败");
         return AjaxResult.error("文件上传失败");
     }
    

    }

    /**

    • 处理压缩包文件

    • @param zipFile 上传压缩包

    • @param destFile 源文件

    • @param extractFolder 解压后文件夹

    • @return R 返回实体类
      */
      private AjaxResult dealZip(MultipartFile zipFile, String fileName, File destFile, File extractFolder) {
      //判断解压后文件夹是否存在
      if (!extractFolder.exists()) {
      //不存在就创建
      extractFolder.mkdirs();
      log.info("解压后文件夹目录 " + extractFolder + " 不存在,已创建");
      }
      try {
      //步骤1、把上传的压缩包文件保存到指定压缩包路径
      zipFile.transferTo(destFile);
      } catch (IOException e) {
      //运行报错直接返回错误信息
      return AjaxResult.error(e.getMessage());
      }

      //步骤2、调用Hutool的ZipUtil压缩工具类的unzip方法来进行对压缩包文件的解压,解压到指定目录
      ZipUtil.unzip(destFile, extractFolder, CharsetUtil.CHARSET_GBK);

      //解压缩完删除原文件(可不删)
      // destFile.delete();

      //步骤3、获取解压后目录下所有的文件
      File[] pdfsUnzip = extractFolder.listFiles();
      log.info("压缩包解压后的内容:" + Arrays.toString(pdfsUnzip));

      //对获取到的文件数组进行判空校验
      if (pdfsUnzip == null || pdfsUnzip.length == 0) {
      //不存在就把压缩文件夹删除(可不删)
      extractFolder.delete();
      log.error("上传失败,压缩包为空");
      return AjaxResult.error("上传失败,压缩包为空");
      }

      //调用方法对解析出来的文件重命名,并移动到指定目录下(/research/pdf)
      File file = new File(extractFolder + "/" + fileName);
      String changeNameResult = changeName(file, fileName);
      if ("文件重命名成功".equals(changeNameResult)) {
      return AjaxResult.success(file);
      } else {
      log.error(changeNameResult);
      return AjaxResult.error(changeNameResult);
      }

    }

    /**

    • @description 修改pdf文件名称为编码, 并把文件移动到指定目录下(/research/pdf)

    • @author zjl

    • @date 2023/9/1 15:32
      */
      public String changeName(File file, String fileName) {
      //文件转存路径对象
      Path targetDirectory = Paths.get("/research/pdf/");
      File targetDirectoryFile = new File("/research/pdf/");
      // Path targetDirectory = Paths.get("D:/research/pdf/");
      // File targetDirectoryFile = new File("D:/research/pdf/");
      //当转存路径不存在时,生成转存路径
      if (!targetDirectoryFile.exists()) {
      targetDirectoryFile.mkdirs();
      log.info("保存pdf文档的目录 " + targetDirectoryFile + " 不存在,已创建");
      }

      try {
      //检查该文件是否是一个目录,如果是目录则获取目录中的所有文件和子目录
      if (file.isDirectory()) {
      File[] files = file.listFiles();
      log.info("重命名的文件为" + Arrays.toString(files));

           //如果目录不为空,则遍历
           if (files != null) {
               for (int i = 0; i < files.length; i++) {
      
                   //如果目录的子集是文件,则进入下方处理
                   if (files[i].isFile()) {
                       log.info("需重命名的文件为:" + files[i]);
      
                       //获取文件的文件名,根据文件名中的 _ 个数,判断文件层级。(3个是市级,4个是地区级)
                       String name = files[i].getName();
                       String fileType = getFileType(name);
                       int count = name.split("_").length - 1;
                       String[] parts = name.split("_");
      
                       //如果为3个 _ 说明当前文件为地市级,取出对应地市的名称,将文件名替换为对应地市的编码
                       //例如:杭州市_20230815_模板名称_2023082214542212.pdf
                       if (count == 4) {
                           //取出地市名称,根据名称在数据库中查询对应的编码。
                           String city = parts[0];
                           String cityId = pdfCodeMapper.selectByName(city);
                           if (null == cityId) {
                               log.error(name + ",文件重命名失败!");
                               continue;
                           }
                           String searchFilename = cityId + fileType;
                           log.info("重命名后的文件名称为:" + searchFilename);
                           //判断当前的编码名称的文件是否已经存在,若存在则需要先删除。renameTo方法不支持覆盖,若存在重名文件会报错
                           boolean fileExists = searchFiles(new File(UPLOAD_DIR + "/" + fileName), searchFilename);
                           if (fileExists) {
                               new File(UPLOAD_DIR + fileName, searchFilename).delete();
                               files[i].renameTo(new File(UPLOAD_DIR + "/" + fileName + "/" + searchFilename));
                           } else {
                               files[i].renameTo(new File(UPLOAD_DIR + "/" + fileName + "/" + searchFilename));
                           }
                           //把文件移动到/research/pdf目录下,重复的覆盖
                           Path sourceFile = Paths.get(UPLOAD_DIR + "/" + fileName + "/" + searchFilename);
                           Files.move(sourceFile, targetDirectory.resolve(sourceFile.getFileName()), StandardCopyOption.REPLACE_EXISTING);
      
                           //如果为4个 _ 说明当前文件为地区级,取出对应地区的名称,将文件名替换为对应地区的编码
                           //例如:杭州市_拱墅区_20230815_模板名称_2023082214542212.pdf
                       } else if (count == 7) {
                           //取出地市的名称,根据名称在数据库中查询对应的编码。
                           String city = parts[1];
                           String cityId = pdfCodeMapper.selectByName(city);
                           if (null == cityId) {
                               log.error(name + ",文件重命名失败!");
                               continue;
                           }
                           String searchFilename = cityId + fileType;
                           log.info("重命名后的文件名称为:" + searchFilename);
                           //判断当前的编码名称的文件是否已经存在,若存在则需要先删除。renameTo方法不支持覆盖,若存在重名文件会报错
                           boolean fileExists = searchFiles(new File(UPLOAD_DIR + "/" + fileName), searchFilename);
                           if (fileExists) {
                               new File(UPLOAD_DIR + fileName, searchFilename).delete();
                               files[i].renameTo(new File(UPLOAD_DIR + "/" + fileName + "/" + searchFilename));
                           } else {
                               files[i].renameTo(new File(UPLOAD_DIR + "/" + fileName + "/" + searchFilename));
                           }
                           //把文件移动到/research/pdf目录下,重复的覆盖
                           Path sourceFile = Paths.get(UPLOAD_DIR + "/" + fileName + "/" + searchFilename);
                           Files.move(sourceFile, targetDirectory.resolve(sourceFile.getFileName()), StandardCopyOption.REPLACE_EXISTING);
                       } else {
                           log.error(name + ",文件名称格式不正确!");
                       }
      
                   }
               }
           }
      
           //解压出来的压缩包没有目录,通过此种方法重命名
       } else if (!file.isDirectory()){
           File file1 = new File(UPLOAD_DIR);
           File[] files = file1.listFiles();
           log.info("解压后文件目录为" + Arrays.toString(files));
      
           for (int i = 0; i < files.length; i++) {
      
               //如果目录的子集是文件,则进入下方处理
               if (files[i].isFile()) {
                   log.info("需重命名的文件为:" + files[i]);
      
                   //获取文件的文件名,根据文件名中的 _ 个数,判断文件层级。(3个是市级,4个是地区级)
                   String name = files[i].getName();
                   String fileType = getFileType(name);
                   int count = name.split("_").length - 1;
                   String[] parts = name.split("_");
      
                   //如果为4个 _ 说明当前文件为地市级,取出对应地市的名称,将文件名替换为对应地市的编码
                   //例如:杭州市_20230815_模板名称_2023082214542212.pdf
                   if (count == 4) {
                       //取出地市名称,根据名称在数据库中查询对应的编码。
                       String city = parts[0];
                       String cityId = pdfCodeMapper.selectByName(city);
                       if (null == cityId) {
                           log.error(name + ",文件重命名失败!");
                           continue;
                       }
                       String searchFilename = cityId + fileType;
                       log.info("重命名后的文件名称为:" + searchFilename);
                       //判断当前的编码名称的文件是否已经存在,若存在则需要先删除。renameTo方法不支持覆盖,若存在重名文件会报错
                       boolean fileExists = searchFiles(new File(UPLOAD_DIR), searchFilename);
                       if (fileExists) {
                           new File(UPLOAD_DIR + fileName, searchFilename).delete();
                           files[i].renameTo(new File(UPLOAD_DIR + "/" + searchFilename));
                       } else {
                           files[i].renameTo(new File(UPLOAD_DIR + "/" + searchFilename));
                       }
                       //把文件移动到/research/pdf目录下,重复的覆盖
                       Path sourceFile = Paths.get(UPLOAD_DIR + "/" +searchFilename);
                       Files.move(sourceFile, targetDirectory.resolve(sourceFile.getFileName()), StandardCopyOption.REPLACE_EXISTING);
      
                       //如果为7个 _ 说明当前文件为地区级,取出对应地区的名称,将文件名替换为对应地区的编码
                       //例如:杭州市_拱墅区_20230815_模板名称_2023082214542212.pdf
                   } else if (count == 7) {
                       //取出地市的名称,根据名称在数据库中查询对应的编码。
                       String city = parts[1];
                       String cityId = pdfCodeMapper.selectByName(city);
                       if (null == cityId) {
                           log.error(name + ",文件重命名失败!");
                           continue;
                       }
                       String searchFilename = cityId + fileType;
                       log.info("重命名后的文件名称为:" + searchFilename);
                       //判断当前的编码名称的文件是否已经存在,若存在则需要先删除。renameTo方法不支持覆盖,若存在重名文件会报错
                       boolean fileExists = searchFiles(new File(UPLOAD_DIR), searchFilename);
                       if (fileExists) {
                           new File(UPLOAD_DIR + fileName, searchFilename).delete();
                           files[i].renameTo(new File(UPLOAD_DIR + "/" + searchFilename));
                       } else {
                           files[i].renameTo(new File(UPLOAD_DIR + "/" + searchFilename));
                       }
                       //把文件移动到/research/pdf目录下,重复的覆盖
                       Path sourceFile = Paths.get(UPLOAD_DIR + "/" + searchFilename);
                       Files.move(sourceFile, targetDirectory.resolve(sourceFile.getFileName()), StandardCopyOption.REPLACE_EXISTING);
                   } else {
                       log.error(name + ",文件名称格式不正确!");
                   }
               }
           }
       }
       return "文件重命名成功";
      

      } catch (Exception e) {
      log.error("文件重命名失败抛出异常: {}", e);
      return "文件重命名失败";
      }
      }

    /**

    • @description 查找指定目录下的文件
    • @author zjl
    • @date 2023/9/1 16:33
      */
      public static boolean searchFiles(File directory, String filename) {
      if (directory.isDirectory()) {
      File[] files = directory.listFiles();
      if (files != null) {
      for (File file : files) {
      if (file.isDirectory()) {
      // 递归搜索子目录
      boolean found = searchFiles(file, filename);
      if (found) {
      return true;
      }
      } else if (file.getName().equals(filename)) {
      // 找到匹配的文件
      return true;
      }
      }
      }
      }
      return false;
      }

    /**

    • @description 取出文件名,不带后缀
    • @author zjl
    • @date 2023/9/6 11:35
      */
      public String subName(MultipartFile file) {
      String fileName = file.getOriginalFilename();
      int dotIndex = fileName.lastIndexOf(".");
      if (dotIndex > 0) {
      return fileName.substring(0, dotIndex);
      }
      return fileName;
      }

    /**

    • @description 取出文件的后缀
    • @author zjl
    • @date 2023/9/6 15:34
      */
      public String getFileType(String fileName) {
      int dotIndex = fileName.lastIndexOf(".");
      if (dotIndex > 0 && dotIndex < fileName.length() - 1) {
      return fileName.substring(dotIndex);
      }
      return "";
      }

    /**

    • @description 根据cityId查询cityName并返回
    • @author zjl91
    • @param[1] null
    • @time 2023/9/22 10:06
      */
      @PostMapping("/cityList")
      @Anonymous
      public AjaxResult getCityList(@RequestBody List researchCountyList) {
      return cityAndCountyService.getCityList(researchCountyList);
      }

}

posted @ 2024-05-17 16:24  小小程序猿、  阅读(378)  评论(0)    收藏  举报