SpringBoot3文件管理

莱莱  金牌会员 | 2023-8-10 08:30:20 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 908|帖子 908|积分 2724

目录

标签:上传.下载.Excel.导入.导出;
一、简介

在项目中,文件管理是常见的复杂功能;
首先文件的类型比较多样,处理起来比较复杂,其次文件涉及大量的IO操作,容易引发内存溢出;
不同的文件类型有不同的应用场景;
比如:图片常用于头像和证明材料;Excel偏向业务数据导入导出;CSV偏向技术层面数据搬运;PDF和Word用于文档类的材料保存等;
下面的案例只围绕普通文件Excel两种类型进行代码实现;
二、工程搭建

1、工程结构


2、依赖管理

普通文件的上传下载,依赖spring-boot框架即可,而Excel类型选择easyexcel组件,该组件内部依赖了apache-poi组件的4.1.2版本;
  1. <dependency>
  2.     <groupId>org.springframework.boot</groupId>
  3.     <artifactId>spring-boot-starter-web</artifactId>
  4.     <version>${spring-boot.version}</version>
  5. </dependency>
  6. <dependency>
  7.     <groupId>com.alibaba</groupId>
  8.     <artifactId>easyexcel</artifactId>
  9.     <version>${easyexcel.version}</version>
  10.     <exclusions>
  11.         <exclusion>
  12.             <groupId>org.slf4j</groupId>
  13.             <artifactId>slf4j-api</artifactId>
  14.         </exclusion>
  15.     </exclusions>
  16. </dependency>
复制代码
三、上传下载

1、配置管理

在配置文件中,添加max-file-size单个文件大小限制和max-request-size请求最大限制两个核心参数;
需要说明的一点是:如何设定参数值的大小,与业务场景和服务器的处理能力都有关系,在测试的过程中优化即可;
  1. spring:
  2.   # 文件配置
  3.   servlet:
  4.     multipart:
  5.       enabled: true
  6.       # 文件单个限制
  7.       max-file-size: 10MB
  8.       # 请求最大限制
  9.       max-request-size: 20MB
复制代码
2、上传下载

这里提供一个文件批量上传接口和一个文件下载接口,把文件管理在工程中的resources/file目录下,下载接口中需要指定该目录下的文件名称;
  1. @RestController
  2. public class FileWeb {
  3.     private static final Logger logger = LoggerFactory.getLogger(FileWeb.class);
  4.     @Resource
  5.     private FileService fileService ;
  6.     /**
  7.      * 文件上传
  8.      */
  9.     @PostMapping("/file/upload")
  10.     public String upload (HttpServletRequest request,
  11.                           @RequestParam("file") MultipartFile[] fileList) throws Exception {
  12.         String uploadUser = request.getParameter("uploadUser");
  13.         if (uploadUser.isEmpty()){
  14.             return "upload-user is empty";
  15.         }
  16.         logger.info("upload-user:{}",uploadUser);
  17.         for (MultipartFile multipartFile : fileList) {
  18.             // 解析文件信息和保存
  19.             fileService.dealFile(multipartFile);
  20.         }
  21.         return "success" ;
  22.     }
  23.     /**
  24.      * 文件下载
  25.      */
  26.     @GetMapping("/file/download")
  27.     public void upload (@RequestParam("fileName") String fileName,
  28.                         HttpServletResponse response) throws Exception {
  29.         if (!fileName.isBlank()){
  30.             String filePath = ResourceUtils.getURL("m1-04-boot-file/src/main/resources/file").getPath();
  31.             File file = new File(filePath,fileName) ;
  32.             response.setHeader("Content-Disposition",
  33.                     "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
  34.             response.setContentType("application/octet-stream");
  35.             Files.copy(Paths.get(file.getPath()), response.getOutputStream());
  36.         }
  37.     }
  38. }
  39. /**
  40. * 文件服务类
  41. */
  42. @Service
  43. public class FileService {
  44.     private static final Logger logger = LoggerFactory.getLogger(FileService.class);
  45.     public void dealFile (MultipartFile multipartFile) throws Exception {
  46.         logger.info("Name >> {}",multipartFile.getName());
  47.         logger.info("OriginalFilename >> {}",multipartFile.getOriginalFilename());
  48.         logger.info("ContentType >> {}",multipartFile.getContentType());
  49.         logger.info("Size >> {}",multipartFile.getSize());
  50.         // 文件输出地址
  51.         String filePath = ResourceUtils.getURL("m1-04-boot-file/src/main/resources/file").getPath();
  52.         File writeFile = new File(filePath, multipartFile.getOriginalFilename());
  53.         multipartFile.transferTo(writeFile);
  54.     }
  55. }
复制代码
使用Postman测试文件批量上传接口:

四、Excel文件

1、Excel创建

基于easyexcel组件中封装的EasyExcel工具类,继承自EasyExcelFactory工厂类,实现Excel单个或多个Sheet的创建,并且在单个Sheet中写多个Table数据表;
  1. @Service
  2. public class ExcelService {
  3.     /**
  4.      * Excel-写单个Sheet
  5.      */
  6.     public static void writeSheet () throws Exception {
  7.         // 文件处理
  8.         String basePath = getAbsolutePath();
  9.         File file = new File(basePath+"/easy-excel-01.xlsx") ;
  10.         checkOrCreateFile(file);
  11.         // 执行写操作
  12.         EasyExcel.write(file).head(DataVO.class)
  13.                 .sheet(0,"用户信息").doWrite(DataVO.getSheet1List());
  14.     }
  15.     /**
  16.      * Excel-写多个Sheet
  17.      */
  18.     public static void writeSheets () throws Exception {
  19.         // 文件处理
  20.         String basePath = getAbsolutePath();
  21.         File file = new File(basePath+"/easy-excel-02.xlsx") ;
  22.         checkOrCreateFile(file);
  23.         ExcelWriter excelWriter = null;
  24.         try {
  25.             excelWriter = EasyExcel.write(file).build();
  26.             // Excel-Sheet1
  27.             WriteSheet writeSheet1 = EasyExcel.writerSheet(0,"分页1").head(DataVO.class).build();
  28.             // Excel-Sheet2
  29.             WriteSheet writeSheet2 = EasyExcel.writerSheet(1,"分页2").head(DataVO.class).build();
  30.             // Excel-Sheet3,写两个Table
  31.             WriteSheet writeSheet3 = EasyExcel.writerSheet(2,"分页3").build();
  32.             WriteTable dataTable = EasyExcel.writerTable(0).head(DataVO.class).build();
  33.             WriteTable dataExtTable = EasyExcel.writerTable(1).head(DataExtVO.class).build();
  34.             // 执行写操作
  35.             excelWriter.write(DataVO.getSheet1List(), writeSheet1);
  36.             excelWriter.write(DataVO.getSheet2List(), writeSheet2);
  37.             excelWriter.write(DataVO.getSheet1List(),writeSheet3,dataTable) ;
  38.             excelWriter.write(DataExtVO.getSheetList(),writeSheet3,dataExtTable) ;
  39.         } catch (Exception e){
  40.             e.printStackTrace();
  41.         } finally {
  42.             if (excelWriter != null){
  43.                 excelWriter.close();
  44.             }
  45.         }
  46.     }
  47. }
  48. /**
  49. * 实体类,这里的注解会解析为Excel中的表头
  50. */
  51. public class DataVO {
  52.     @ExcelProperty("编号")
  53.     private Integer id ;
  54.     @ExcelProperty("名称")
  55.     private String name ;
  56.     @ExcelProperty("手机号")
  57.     private String phone ;
  58.     @ExcelProperty("城市")
  59.     private String cityName ;
  60.     @ExcelProperty("日期")
  61.     private Date date ;
  62. }
复制代码
文件效果:

2、Excel读取

对于读取Excel文件来说,则需要根据具体的样式来定了,在easyexcel组件中还可以添加读取过程的监听器;
  1. @Service
  2. public class ExcelService {
  3.     /**
  4.      * Excel-读取数据
  5.      */
  6.     public static void readExcel () throws Exception {
  7.         // 文件处理
  8.         String basePath = getAbsolutePath();
  9.         File file = new File(basePath+"/easy-excel-01.xlsx") ;
  10.         if (!file.exists()){
  11.             return ;
  12.         }
  13.         // 读取数据
  14.         List<DataVO> dataList = EasyExcel.read(file).head(DataVO.class)
  15.                 .sheet(0).headRowNumber(1).doReadSync();
  16.         dataList.forEach(System.out::println);
  17.     }
  18.     /**
  19.      * Excel-读取数据使用解析监听器
  20.      */
  21.     public static void readExcelListener () throws Exception {
  22.         // 文件处理
  23.         String basePath = getAbsolutePath();
  24.         File file = new File(basePath+"/easy-excel-01.xlsx") ;
  25.         if (!file.exists()){
  26.             return ;
  27.         }
  28.         // 读取数据,并且使用解析监听器
  29.         DataListener dataListener = new DataListener() ;
  30.         List<DataVO> dataSheetList = EasyExcel.read(file,dataListener).head(DataVO.class)
  31.                 .sheet(0).headRowNumber(1).doReadSync();
  32.         dataSheetList.forEach(System.out::println);
  33.     }
  34. }
复制代码
3、解析监听

继承AnalysisEventListener类,并重写其中的方法,可以监听Excel的解析过程,或者添加一些自定义的处理逻辑;
  1. public class DataListener extends AnalysisEventListener<DataVO> {
  2.     /**
  3.      * 接收解析的数据块
  4.      */
  5.     @Override
  6.     public void invoke(DataVO data, AnalysisContext context) {
  7.         System.out.println("DataListener:"+data);
  8.     }
  9.     /**
  10.      * 接收解析的表头
  11.      */
  12.     @Override
  13.     public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
  14.         System.out.println("DataListener:"+headMap);
  15.     }
  16.     @Override
  17.     public void doAfterAllAnalysed(AnalysisContext context) {
  18.         System.out.println("DataListener:after...all...analysed");
  19.     }
  20. }
复制代码
4、导入导出

实际上Excel文件的导入导出,原理与文件的上传下载类似,只不过这里使用easyexcel组件中的API来直接处理Excel的写和读;
  1. @RestController
  2. public class ExcelWeb {
  3.     @GetMapping("excel/download")
  4.     public void download(HttpServletResponse response) throws IOException {
  5.         response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
  6.         response.setCharacterEncoding("utf-8");
  7.         String fileName = URLEncoder.encode("Excel数据", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
  8.         response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
  9.         EasyExcel.write(response.getOutputStream(), DataVO.class).sheet("用户").doWrite(DataVO.getSheet1List());
  10.     }
  11.     @ResponseBody
  12.     @PostMapping("excel/upload")
  13.     public String upload(@RequestParam("file") MultipartFile file) throws IOException {
  14.         List<DataVO> dataList = EasyExcel
  15.                 .read(file.getInputStream(), DataVO.class, new DataListener()).sheet().doReadSync();
  16.         dataList.forEach(System.out::println);
  17.         return "success";
  18.     }
  19. }
复制代码
使用Postman测试单个Excel上传接口:

五、参考源码
  1. 文档仓库:
  2. https://gitee.com/cicadasmile/butte-java-note
  3. 源码仓库:
  4. https://gitee.com/cicadasmile/butte-spring-parent
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

莱莱

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表