SpringBoot3文件管理

news2024/11/22 16:54:30

标签:上传.下载.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);
    @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

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

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

相关文章

Codeforces Round 890 (Div. 2) C. To Become Max(二分 补写法 二分套二分)

题目 给定一个长度为n(n<1e3)的数组&#xff0c; 在一次操作里&#xff0c;你可以选择一个满足a[i]<a[i1]的下标i(1<i<n-1)&#xff0c;对a[i]加一 问&#xff0c;你最多操作k次的情况下&#xff0c;数组的最大值是多少&#xff0c;输出最大值 思路来源 Submi…

【C++精华铺】5.C++类和对象(中)类的六个默认成员函数

目录 1. 六个默认成员函数 2. 构造函数 2.1 概念 2.2 默认构造 2.2.1 系统生成的默认构造 2.2.2 自定义默认构造函数 2.3 构造函数的重载 3. 析构函数 3.1 概念 3.2 系统生成的析构函数 3.3 自定义析构函数 4. 拷贝构造 4.1 概念 4.2 默认生成的拷贝构造&#xff08;浅…

解锁滴滴ES的性能潜力:JDK 17和ZGC的升级之路

前文介绍了滴滴自研的ES强一致性多活是如何实现的&#xff0c;其中也提到为了提升查询性能和解决查询毛刺问题&#xff0c;滴滴ES原地升级JDK17和ZGC&#xff0c;在这个过程中我们遇到了哪些问题&#xff0c;怎样解决的&#xff0c;以及最终上线效果如何&#xff0c;这篇文章就…

云计算技术——多GPU渲染的云渲染服务

多GPU渲染的云渲染服务&#xff0c;是一种利用云计算技术&#xff0c;将多个图形处理器&#xff08;GPU&#xff09;集成在一起&#xff0c;为用户提供高效、便捷、低成本的渲染解决方案的服务。本文将从多GPU渲染的概念、优势、应用场景&#xff0c;云渲染服务的特点、优势&am…

【C++】初阶 --- 内联函数(inline)

文章目录 &#x1f95e;内联函数&#x1f35f;1、C语言实现"宏函数"&#x1f35f;2、内联函数的概念&#x1f35f;3、内联函数的特性&#x1f35f;4、总结 &#x1f95e;内联函数 &#x1f35f;1、C语言实现"宏函数" &#x1f970;用C语言先来实现普通的…

并发——volatile 关键字

文章目录 1. CPU 缓存模型2. 讲一下 JMM(Java 内存模型)3. 并发编程的三个重要特性4. 说说 synchronized 关键字和 volatile 关键字的区别 我们先要从 CPU 缓存模型 说起&#xff01; 1. CPU 缓存模型 为什么要弄一个 CPU 高速缓存呢&#xff1f; 类比我们开发网站后台系统使…

分布式 - 服务器Nginx:一小时入门系列之静态网页配置

文章目录 1. 静态文件配置2. nginx listen 命令解析3. nginx server_name 命令解析4. nginx server 端口重复5. nginx location 命令 1. 静态文件配置 在 /home 文件下配置一个静态的AdminLTE后台管理系统&#xff1a; [rootnginx-dev conf.d]# cd /home [rootnginx-dev home…

flutter项目给安卓打正式包 和升级版本号

1.首先把flutter项目里的android目录整个拖进android studo里,运行一下看看是否能运行 2.Build->Generate Signed Bundle/APK… 点击APK->Next 如果没有key酒店及Create new…就生成新的key 点击Key store path:右边的图标选择保存路径 选择保存的路径,并且在Save…

【雕爷学编程】Arduino动手做(01)---干簧管传感器模块4

37款传感器与模块的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&#x…

logo一键生成的操作,没有设计经验也无妨

您可能会担心&#xff0c;没有设计经验如何设计一个独特而专业的标志&#xff08;Logo&#xff09;。但是&#xff0c;随着技术的进步&#xff0c;现在有许多一键生成操作的设计工具可供使用&#xff0c;使人们更容易创建自己的Logo。 什么是一键生成操作&#xff1f; 一键生成…

若依vue -【 100 ~ 更 】

100 主子表代码生成详解 1 新建数据库表结构&#xff08;主子表&#xff09; -- ---------------------------- -- 客户表 -- ---------------------------- drop table if exists sys_customer; create table sys_customer (customer_id bigint(20) not null…

《大型网站技术架构》第二篇 架构-高可用

高可用在公司中的重要性 对公司而言&#xff0c;可用性关系网站的生死存亡。对个人而言&#xff0c;可用性关系到自己的绩效升迁。 工程师对架构做了许多优化、对代码做了很多重构&#xff0c;对性能、扩展性、伸缩性做了很多改善&#xff0c;但别人未必能直观地感受到&#…

字节编码学习

字节编码学习 文章目录 字节编码学习01_字节与ASCII码表02_每个国家都有独特的码表03_国际化UTF-804_编码本和解码本不一致&#xff0c;乱码 01_字节与ASCII码表 public class Demo01 {public static void main(String[] args) {// 计算机的底层全部都是字节 ---- ----// 一个…

Android Studio实现简单ListView

效果图 MainActivity package com.example.listviewtest;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle; import android.widget.ListView;import com.example.listviewtest.adapter.PartAdapter; import com.example.listviewtest.bean.PartB…

多目标优化之MOEA-D算法,MATLAB代码,免费获取

今天给大家分享一期MOEA/D算法。1 引言 基于分解的多目标进化算法(MOEA/D)的核心思想将多目标优化问题被转化为一系列单目标优化子问题或者是多个多目标的子问题&#xff0c;然后利用子问题之间的邻域关系&#xff0c;采用协作的方式对这些子问题同时进行优化。从而向整个Paret…

大麦订单截图 一键生成订单截图

新版付款图样式展示 这个样式图就是在大麦刚付款完的一个订单截图&#xff0c;它的状态是等待卖家发货 下滑下载源码 下载源码&#xff1a;https://pan.baidu.com/s/16lN3gvRIZm7pqhvVMYYecQ?pwd6zw3

LoRaWAN网关与网络服务器(NS)的通信LNS协议介绍

将 LoRaWAN网关连接到 LoRaWAN 网络服务器 (LNS) 是一个两步过程,该过程使用 WebSocket 作为传输协议来交换包含 JSON 编码对象的文本记录。 首先,网关向LNS查询LNS实际连接端点的URI。其次,它与该端点建立数据连接以接收设置信息。从那时起,LoRa 上行链路和下行链路帧通过…

golang专栏

GOLANG专栏订阅会员 Golang基础教程 Golang基础教程 Golang练手算法 Golang练手算法 Golang设计模式 Golang设计模式 Golang数据结构和算法 Golang数据结构和算法 Golang并发编程 Golang并发编程 ORM框架Gorm Golang ORM框架gorm Golang源码分析 Golang源码分析 MySQL教…

校园防欺凌防霸凌该怎么做

校园防欺凌防霸凌该怎么做 校园防欺凌和霸凌是一个长期而全面的过程&#xff0c;需要学生、教师和家长共同参与和努力。以下是一些可以采取的措施&#xff1a; 1. 教育和意识提高&#xff1a;通过教育和培训&#xff0c;提高学生、教师和家长对欺凌和霸凌的认识和了解。学校可…

机器人制作开源方案 | 超市服务机器人

作者&#xff1a;林江斌 岳沛霖 李锦扬 单位&#xff1a;北京理工大学 机械与车辆学院 指导老师&#xff1a;李忠新 朱杰 一、作品简介 1.设计背景 当前社会疫情防控已经成为常态化&#xff0c;超市是人员流动相对密集的公共场所&#xff0c;超市防疫也是社会防疫工作中重要…