SpringBoot3文件管理操作方法
一、简介
在项目中,文件管理是常见的复杂功能;
首先文件的类型比较多样,处理起来比较复杂,其次文件涉及大量的IO操作,容易引发内存溢出;
不同的文件类型有不同的应用场景;
比如:图片常用于头像和证明材料;Excel偏向业务数据导入导出;CSV偏向技术层面数据搬运;PDF和Word用于文档类的材料保存等;
下面的案例只围绕普通文件和Excel两种类型进行代码实现;
二、工程搭建
1、工程结构
2、依赖管理
普通文件的上传下载,依赖 spring-boot
框架即可,而Excel类型选择 easyexcel
组件,该组件内部依赖了 apache-poi
组件的 4.1.2
版本;
<!-- 基础框架组件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>${spring-boot.version}</version> </dependency> <!-- Excel组件 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>${easyexcel.version}</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </exclusion> </exclusions> </dependency>
三、上传下载
1、配置管理
在配置文件中,添加 max-file-size
单个文件大小限制和 max-request-size
请求最大限制两个核心参数;
需要说明的一点是:如何设定参数值的大小,与业务场景和服务器的处理能力都有关系,在测试的过程中优化即可;
spring: # 文件配置 servlet: multipart: enabled: true # 文件单个限制 max-file-size: 10MB # 请求最大限制 max-request-size: 20MB
2、上传下载
这里提供一个文件批量上传接口和一个文件下载接口,把文件管理在工程中的 resources/file
目录下,下载接口中需要指定该目录下的文件名称;
@RestController public class FileWeb { private static final Logger logger = LoggerFactory.getLogger(FileWeb.class); @Resource private FileService fileService ; /** * 文件上传 */ @PostMapping("/file/upload") public String upload (HttpServletRequest request, @RequestParam("file") MultipartFile[] fileList) throws Exception { String uploadUser = request.getParameter("uploadUser"); if (uploadUser.isEmpty()){ return "upload-user is empty"; } logger.info("upload-user:{}",uploadUser); for (MultipartFile multipartFile : fileList) { // 解析文件信息和保存 fileService.dealFile(multipartFile); } return "success" ; } /** * 文件下载 */ @GetMapping("/file/download") public void upload (@RequestParam("fileName") String fileName, HttpServletResponse response) throws Exception { if (!fileName.isBlank()){ String filePath = ResourceUtils.getURL("m1-04-boot-file/src/main/resources/file").getPath(); File file = new File(filePath,fileName) ; response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8)); response.setContentType("application/octet-stream"); Files.copy(Paths.get(file.getPath()), response.getOutputStream()); } } } /** * 文件服务类 */ @Service public class FileService { private static final Logger logger = LoggerFactory.getLogger(FileService.class); public void dealFile (MultipartFile multipartFile) throws Exception { logger.info("Name >> {}",multipartFile.getName()); logger.info("OriginalFilename >> {}",multipartFile.getOriginalFilename()); logger.info("ContentType >> {}",multipartFile.getContentType()); logger.info("Size >> {}",multipartFile.getSize()); // 文件输出地址 String filePath = ResourceUtils.getURL("m1-04-boot-file/src/main/resources/file").getPath(); File writeFile = new File(filePath, multipartFile.getOriginalFilename()); multipartFile.transferTo(writeFile); } }
使用Postman测试文件批量上传接口:
四、Excel文件
1、Excel创建
基于 easyexcel
组件中封装的 EasyExcel
工具类,继承自 EasyExcelFactory
工厂类,实现Excel单个或多个 Sheet
的创建,并且在单个 Sheet
中写多个 Table
数据表;
@Service public class ExcelService { /** * Excel-写单个Sheet */ public static void writeSheet () throws Exception { // 文件处理 String basePath = getAbsolutePath(); File file = new File(basePath+"/easy-excel-01.xlsx") ; checkOrCreateFile(file); // 执行写操作 EasyExcel.write(file).head(DataVO.class) .sheet(0,"用户信息").doWrite(DataVO.getSheet1List()); } /** * Excel-写多个Sheet */ public static void writeSheets () throws Exception { // 文件处理 String basePath = getAbsolutePath(); File file = new File(basePath+"/easy-excel-02.xlsx") ; checkOrCreateFile(file); ExcelWriter excelWriter = null; try { excelWriter = EasyExcel.write(file).build(); // Excel-Sheet1 WriteSheet writeSheet1 = EasyExcel.writerSheet(0,"分页1").head(DataVO.class).build(); // Excel-Sheet2 WriteSheet writeSheet2 = EasyExcel.writerSheet(1,"分页2").head(DataVO.class).build(); // Excel-Sheet3,写两个Table WriteSheet writeSheet3 = EasyExcel.writerSheet(2,"分页3").build(); WriteTable dataTable = EasyExcel.writerTable(0).head(DataVO.class).build(); WriteTable dataExtTable = EasyExcel.writerTable(1).head(DataExtVO.class).build(); // 执行写操作 excelWriter.write(DataVO.getSheet1List(), writeSheet1); excelWriter.write(DataVO.getSheet2List(), writeSheet2); excelWriter.write(DataVO.getSheet1List(),writeSheet3,dataTable) ; excelWriter.write(DataExtVO.getSheetList(),writeSheet3,dataExtTable) ; } catch (Exception e){ e.printStackTrace(); } finally { if (excelWriter != null){ excelWriter.close(); } } } } /** * 实体类,这里的注解会解析为Excel中的表头 */ public class DataVO { @ExcelProperty("编号") private Integer id ; @ExcelProperty("名称") private String name ; @ExcelProperty("手机号") private String phone ; @ExcelProperty("城市") private String cityName ; @ExcelProperty("日期") private Date date ; }
文件效果:
2、Excel读取
对于读取Excel文件来说,则需要根据具体的样式来定了,在 easyexcel
组件中还可以添加读取过程的监听器;
@Service public class ExcelService { /** * Excel-读取数据 */ public static void readExcel () throws Exception { // 文件处理 String basePath = getAbsolutePath(); File file = new File(basePath+"/easy-excel-01.xlsx") ; if (!file.exists()){ return ; } // 读取数据 List<DataVO> dataList = EasyExcel.read(file).head(DataVO.class) .sheet(0).headRowNumber(1).doReadSync(); dataList.forEach(System.out::println); } /** * Excel-读取数据使用解析监听器 */ public static void readExcelListener () throws Exception { // 文件处理 String basePath = getAbsolutePath(); File file = new File(basePath+"/easy-excel-01.xlsx") ; if (!file.exists()){ return ; } // 读取数据,并且使用解析监听器 DataListener dataListener = new DataListener() ; List<DataVO> dataSheetList = EasyExcel.read(file,dataListener).head(DataVO.class) .sheet(0).headRowNumber(1).doReadSync(); dataSheetList.forEach(System.out::println); } }
3、解析监听
继承 AnalysisEventListener
类,并重写其中的方法,可以监听Excel的解析过程,或者添加一些自定义的处理逻辑;
public class DataListener extends AnalysisEventListener<DataVO> { /** * 接收解析的数据块 */ @Override public void invoke(DataVO data, AnalysisContext context) { System.out.println("DataListener:"+data); } /** * 接收解析的表头 */ @Override public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) { System.out.println("DataListener:"+headMap); } @Override public void doAfterAllAnalysed(AnalysisContext context) { System.out.println("DataListener:after...all...analysed"); } }
4、导入导出
实际上Excel文件的导入导出,原理与文件的上传下载类似,只不过这里使用 easyexcel
组件中的API来直接处理Excel的写和读;
@RestController public class ExcelWeb { @GetMapping("excel/download") public void download(HttpServletResponse response) throws IOException { response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); String fileName = URLEncoder.encode("Excel数据", StandardCharsets.UTF_8).replaceAll("\\+", "%20"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); EasyExcel.write(response.getOutputStream(), DataVO.class).sheet("用户").doWrite(DataVO.getSheet1List()); } @ResponseBody @PostMapping("excel/upload") public String upload(@RequestParam("file") MultipartFile file) throws IOException { List<DataVO> dataList = EasyExcel .read(file.getInputStream(), DataVO.class, new DataListener()).sheet().doReadSync(); dataList.forEach(System.out::println); return "success"; } }
使用Postman测试单个Excel上传接口:
五、参考源码
文档仓库: https://gitee.com/cicadasmile/butte-java-note 源码仓库: https://gitee.com/cicadasmile/butte-spring-parent
Gitee主页: https://gitee.com/cicadasmile/butte-java-note
到此这篇关于SpringBoot3文件管理的文章就介绍到这了,更多相关SpringBoot文件管理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
浅谈java.util.concurrent包中的线程池和消息队列
这篇文章主要介绍了浅谈java.util.concurrent包中的线程池和消息队列,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2019-08-08Springboot之restTemplate的配置及使用方式
这篇文章主要介绍了Springboot之restTemplate的配置及使用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-10-10
最新评论