写点什么

SpringBoot3 文件管理

作者:知了一笑
  • 2023-08-10
    浙江
  • 本文字数:4723 字

    阅读完需:约 15 分钟

SpringBoot3文件管理

标签:上传.下载.Excel.导入.导出;

一、简介

在项目中,文件管理是常见的复杂功能;


首先文件的类型比较多样,处理起来比较复杂,其次文件涉及大量的 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目录下,下载接口中需要指定该目录下的文件名称;


@RestControllerpublic 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()); } }}
/** * 文件服务类 */@Servicepublic 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数据表;


@Servicepublic 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组件中还可以添加读取过程的监听器;


@Servicepublic 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 的写和读;


@RestControllerpublic 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
复制代码


发布于: 刚刚阅读数: 4
用户头像

知了一笑

关注

公众号:知了一笑 2020-04-08 加入

源码仓库:https://gitee.com/cicadasmile

评论

发布
暂无评论
SpringBoot3文件管理_Java_知了一笑_InfoQ写作社区