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目录下,下载接口中需要指定该目录下的文件名称;

@RestController
public class FileWeb {private static final Logger logger = LoggerFactory.getLogger(FileWeb.class);@Resourceprivate 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-Sheet1WriteSheet writeSheet1 = EasyExcel.writerSheet(0,"分页1").head(DataVO.class).build();// Excel-Sheet2WriteSheet writeSheet2 = EasyExcel.writerSheet(1,"分页2").head(DataVO.class).build();// Excel-Sheet3,写两个TableWriteSheet 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> {/*** 接收解析的数据块*/@Overridepublic void invoke(DataVO data, AnalysisContext context) {System.out.println("DataListener:"+data);}/*** 接收解析的表头*/@Overridepublic void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {System.out.println("DataListener:"+headMap);}@Overridepublic 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/29916.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

redis的配置和使用、redis的数据结构以及缓存遇见的常见问题

目录 1.缓存 2.redis不仅仅可以做缓存&#xff0c;只不过说他的大部分场景&#xff0c;是做缓存。本地缓存重启后缓存里的东西就没有了&#xff0c;但是redis有。 3.redis有几个特性:查询快&#xff0c;但是是放到内存里的〈断电或者重启&#xff0c;数据就丢了)&#xff0c…

Vue组件化开发思想;Vue的全局组件;Vue的局部组件;Vue的开发模式和解析;Vue CLI安装和使用;Vue项目的创建方式–Vite

目录 1_Vue组件化开发思想1.1_认识组件化开发1.2_Vue的组件化1.3_注册组件的方式 2_Vue的全局组件3_Vue的局部组件4_Vue的开发模式和解析4.1_Vue的开发模式4.2_单文件的特点4.3_如何支持SFC4.4_VSCode对SFC文件的支持 5_Vue CLI安装和使用5.1_Vue CLI脚手架5.2_Vue CLI 安装和使…

基于react-native的简单消息确认框showModel

基于react-native的简单消息确认框showModel 效果示例图组件代码ShowModel/index.jsx使用案例device.js安装线性渐变色 效果示例图 组件代码ShowModel/index.jsx import React, {forwardRef, useImperativeHandle, useState} from react; import {View,Text,Modal,TouchableOp…

06微服务间的通信方式

一句话导读 微服务设计的一个挑战就是服务间的通信问题&#xff0c;服务间通信理论上可以归结为进程间通信&#xff0c;进程可以是同一个机器上的&#xff0c;也可以是不同机器的。服务可以使用同步请求响应机制通信&#xff0c;也可以使用异步的基于消息中间件间的通信机制。同…

Vue2-简介、模板语法、数据绑定、MVVM、数据代理、事件处理

&#x1f954;&#xff1a;成功之后就能光明正大地回望所有苦难 VUE-Day1 Vue简介1、Vue是什么&#xff1f;2、谁开发的&#xff1f; 发展历程&#xff1f;3、Vue的特点4、容器和实例、实例中的el和data总结 Vue模板语法插值语法指令语法 数据绑定1.单向数据绑定&#xff08;v-…

51单片机学习--DS18B20温度读取温度报警器

需要先编写OneWire模块&#xff0c;再在DS18B20模块中调用OneWire模块的函数 先根据原理图做好端口的声明&#xff1a; sbit OneWire_DQ P3^7;接下来像之前一样把时序结构用代码模拟出来&#xff1a; unsigned char OneWire_Init(void) {unsigned char i;unsigned char Ac…

opencv基础49-图像轮廓02-矩特征cv2.moments()->(形状分析、物体检测、图像识别、匹配)

矩特征&#xff08;Moments Features&#xff09;是用于图像分析和模式识别的一种特征表示方法&#xff0c;用来描述图像的形状、几何特征和统计信息。矩特征可以用于识别图像中的对象、检测形状以及进行图像分类等任务。 矩特征通过计算图像像素的高阶矩来提取特征。这些矩可以…

Towards Open World Object Detection【论文解析】

Towards Open World Object Detection 摘要1 介绍2 相关研究3 开放世界目标检测4 ORE:开放世界目标检测器4.1 对比聚类4.2 RPN自动标注未知类别4.3 基于能量的未知标识4.4 减少遗忘 5 实验5.1开放世界评估协议5.2 实现细节5.3 开放世界目标检测结果5.4 增量目标检测结果 6 讨论…

VoxWeekly|The Sandbox 生态周报|20230807

欢迎来到由 The Sandbox 发布的《VoxWeekly》。我们会在每周发布&#xff0c;对上一周 The Sandbox 生态系统所发生的事情进行总结。 如果你喜欢我们内容&#xff0c;欢迎与朋友和家人分享。请订阅我们的 Medium 、关注我们的 Twitter&#xff0c;并加入 Discord 社区&#xf…

【Vue3】keep-alive 缓存组件

当在 Vue.js 中使用 <keep-alive> 组件时&#xff0c;它将会缓存动态组件&#xff0c;而不是每次渲染都销毁和重新创建它们。这对于需要在组件间快速切换并且保持组件状态的情况非常有用。 <keep-alive> 只能包含&#xff08;或者说只能渲染&#xff09;一个子组件…

CANoe通过Frame Histogram窗口统计报文周期(方便快捷)

文章目录 效果展示1.插入Frame Histogram窗口2.Activate3.运行CANoe&#xff0c;停止后查看write窗口 效果展示 统计报文周期信息输出在write窗口。 1.插入Frame Histogram窗口 2.Activate 3.运行CANoe&#xff0c;停止后查看write窗口 统计报文周期信息输出在write窗口。

04-2_Qt 5.9 C++开发指南_SpinBox使用

文章目录 1. SpinBox简介2. SpinBox使用2.1 可视化UI设计2.2 widget.h2.3 widget.cpp 1. SpinBox简介 QSpinBox 用于整数的显示和输入&#xff0c;一般显示十进制数&#xff0c;也可以显示二进制、十六进制的数&#xff0c;而且可以在显示框中增加前缀或后缀。 QDoubleSpinBox…

机器学习笔记:李宏毅ChatGPT课程1:刨析ChatGPT

ChatGPT——Chat Generative Pre-trained Transformer 1 文字接龙 每次输出一个概率分布&#xff0c;根据概率sample一个答案 ——>因为是根据概率采样&#xff0c;所以ChatGPT每次的答案是不一样的&#xff08;把生成式学习拆分成多个分类问题&#xff09;将生成的答案加到…

Linux(进程)

Linux&#xff08;进程&#xff09; 1. 冯诺依曼结构体系2 . 操作系统&#xff08;OS&#xff09;3.进程task_ struct内容分类查看进程查看PID以及PPIDfork()Linux操作系统进程的状态僵尸进程孤儿进程进程优先级其他概念 1. 冯诺依曼结构体系 冯诺依曼结构也称普林斯顿结构&am…

ArcGIS、ENVI、InVEST、FRAGSTATS技术教程

专题一 空间数据获取与制图 1.1 软件安装与应用讲解 1.2 空间数据介绍 1.3海量空间数据下载 1.4 ArcGIS软件快速入门 1.5 Geodatabase地理数据库 专题二 ArcGIS专题地图制作 2.1专题地图制作规范 2.2 空间数据的准备与处理 2.3 空间数据可视化&#xff1a;地图符号与注…

机器学习、深度学习项目开发业务数据场景梳理汇总记录二

本文的主要作用是对历史项目开发过程中接触到的业务数据进行整体的汇总梳理&#xff0c;文章会随着项目的开发推进不断更新。 这里是续文&#xff0c;因为CSDN单篇文章内容太大的话就会崩溃的&#xff0c;别问我怎么知道的&#xff0c;问就是血泪教训&#xff0c;辛辛苦苦写了一…

泰国的区块链和NFT市场调研

泰国的区块链和NFT市场调研 基本介绍 参考&#xff1a; https://zh.wikipedia.org/zh-hans/%E6%B3%B0%E5%9B%BD参考&#xff1a; https://hktdc.infogram.com/thsc–1h7k2303zo75v2x zz制度&#xff1a; 君主立宪制&#xff08;议会制&#xff09; 国王&#xff1a; 玛哈哇集拉…

如何给Google Chrome增加proxy

1. 先打开https://github.com/KaranGauswami/socks-to-http-proxy/releases 我的电脑是Liunx系统所以下载第一个 2. 下载完之后把这个文件变成可执行文件&#xff0c;可以是用这个命令 chmod x 文件名 3. 然后执行这个命令&#xff1a; ./sthp-linux -p 8080 -s 127.0.0.1:…

HTTP协议

HTTP协议 应用层再谈 "协议"网络版计算器 HTTP协议认识URLurlencode和urldecodeHTTP协议格式HTTP的方法HTTP的状态码HTTP常见Header HTTPS协议HTTPS 是什么什么是"加密"为什么要加密常⻅的加密⽅式 HTTPS 的⼯作过程探究⽅案 1 - 只使⽤对称加密⽅案 2 - 只…

HBase-读流程

创建连接同写流程。 &#xff08;1&#xff09;读取本地缓存中的Meta表信息&#xff1b;&#xff08;第一次启动客户端为空&#xff09; &#xff08;2&#xff09;向ZK发起读取Meta表所在位置的请求&#xff1b; &#xff08;3&#xff09;ZK正常返回Meta表所在位置&#x…