Spring Boot 文件上传与下载(图片 _ Excel)

Spring Boot 文件上传与下载(图片 / Excel)

在Spring Boot纯接口开发熟练掌握后,文件操作便成为进阶必备技能——无论是日常开发中的图片上传、Excel导入导出,还是各类小工具的核心功能,都离不开文件的上传与解析。本文承接纯接口开发的基础,手把手实战本地文件上传、图片上传与回显、Excel文件上传解析(兼顾POI与EasyExcel两种主流方式),全程贴合实际开发场景,帮你快速掌握文件操作核心,为后续开发小工具筑牢基础。

一、前置准备:环境搭建与核心配置

文件操作核心依赖为文件上传组件、Excel解析组件(POI/EasyExcel),同时需配置文件存储路径、上传大小限制,避免出现上传失败、文件过大等问题。

1.1 Maven 核心依赖

按需引入依赖,其中EasyExcel相比POI更轻量、内存占用更低,适合大数据量Excel解析;POI兼容性更强,适合复杂Excel操作,可根据需求选择:

<!-- Spring Boot Web 核心依赖(文件上传依赖已集成) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- 图片处理依赖(可选,用于图片压缩、格式转换) -->
<dependency>
    <groupId>net.coobird</groupId>
    <artifactId>thumbnailator</artifactId>
    <version>0.4.19</version>
</dependency>

<!-- POI 依赖(Excel解析,兼容复杂Excel) -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.1.2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.1.2</version>
</dependency>

<!-- EasyExcel 依赖(Excel解析,轻量高效,推荐) -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.3.2</version>
</dependency>

<!-- lombok 简化代码 -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

<!-- commons-io 工具类(简化文件操作) -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
</dependency>

1.2 核心配置(application.yml)

配置文件上传大小限制、本地存储路径、图片访问路径,集中管理,便于后续修改和维护:

spring:
  # 文件上传配置
  servlet:
    multipart:
      enabled: true # 开启文件上传
      max-file-size: 10MB # 单个文件最大大小(根据需求调整,如Excel可设为50MB)
      max-request-size: 100MB # 单次请求最大文件大小

# 自定义文件存储配置
file:
  # 本地存储根路径(建议使用绝对路径,避免部署时路径混乱)
  upload-path: D:/springboot-file/upload/
  # 图片访问路径前缀(用于图片回显,与下面的静态资源配置对应)
  image-access-path: /upload/images/
  # Excel存储路径(单独划分,便于管理)
  excel-upload-path: ${file.upload-path}excel/
  # 普通文件存储路径
  common-upload-path: ${file.upload-path}common/

# Spring MVC 静态资源配置(关键:让前端能访问本地上传的图片)
spring:
  mvc:
    static-path-pattern: /upload/**
  web:
    resources:
      static-locations: file:${file.upload-path}

关键说明:1. 存储路径建议使用绝对路径,Windows系统如D:/springboot-file/upload/,Linux系统如/root/springboot-file/upload/;2. 静态资源配置必须正确,否则前端无法通过URL回显图片;3. 上传大小限制需根据业务调整,避免过小导致无法上传大文件。

1.3 工具类准备(文件操作通用工具)

封装通用文件操作方法(创建目录、生成唯一文件名、删除文件),避免重复代码,提升开发效率:

import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

/**
 * 文件操作通用工具类
 */
@Component
public class FileUtil {

    // 注入配置文件中的存储路径
    @Value("${file.upload-path}")
    private String uploadRootPath;
    @Value("${file.image-access-path}")
    private String imageAccessPath;
    @Value("${file.excel-upload-path}")
    private String excelUploadPath;
    @Value("${file.common-upload-path}")
    private String commonUploadPath;

    /**
     * 生成唯一文件名(避免文件名重复,覆盖文件)
     * @param originalFilename 原始文件名
     * @return 唯一文件名(UUID + 后缀名)
     */
    public String generateUniqueFileName(String originalFilename) {
        // 获取文件后缀名(如.jpg、.xlsx)
        String suffix = FilenameUtils.getExtension(originalFilename);
        // 生成UUID(唯一标识),拼接后缀名
        return UUID.randomUUID().toString() + "." + suffix;
    }

    /**
     * 创建目录(若目录不存在则创建)
     * @param filePath 目录路径
     */
    public void createDirectory(String filePath) {
        File file = new File(filePath);
        if (!file.exists()) {
            // 递归创建目录(包括父目录)
            file.mkdirs();
        }
    }

    /**
     * 上传文件到指定目录
     * @param file 上传的文件(MultipartFile)
     * @param targetDir 目标存储目录(如图片、Excel目录)
     * @return 完整的文件存储路径(物理路径)
     */
    public String uploadFile(MultipartFile file, String targetDir) throws IOException {
        // 1. 校验文件是否为空
        if (file.isEmpty()) {
            throw new IOException("上传文件不能为空");
        }
        // 2. 创建目标目录(若不存在)
        createDirectory(targetDir);
        // 3. 生成唯一文件名
        String uniqueFileName = generateUniqueFileName(file.getOriginalFilename());
        // 4. 拼接完整物理路径
        String physicalPath = targetDir + File.separator + uniqueFileName;
        // 5. 上传文件(将MultipartFile转换为本地文件)
        file.transferTo(new File(physicalPath));
        // 6. 返回物理路径
        return physicalPath;
    }

    /**
     * 获取图片访问URL(用于前端回显)
     * @param uniqueFileName 唯一文件名
     * @return 图片访问URL(如:http://localhost:8080/upload/images/xxx.jpg)
     */
    public String getImageAccessUrl(String uniqueFileName) {
        return imageAccessPath + uniqueFileName;
    }

    // 以下为getter方法,供外部获取路径
    public String getExcelUploadPath() {
        return excelUploadPath;
    }

    public String getCommonUploadPath() {
        return commonUploadPath;
    }
}

二、核心实战一:本地文件上传(通用版)

本地文件上传是基础,核心逻辑:接收前端传入的MultipartFile文件 → 校验文件合法性(大小、格式) → 生成唯一文件名 → 上传到指定本地目录 → 返回文件存储路径或访问URL。适用于所有类型文件(文档、压缩包等)。

2.1 接口设计(Controller)

提供通用文件上传接口,支持单个文件上传,可通过参数指定文件类型(用于区分存储目录):

import com.example.demo.util.FileUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 通用文件上传控制器
 */
@RestController
@RequestMapping("/file")
public class FileUploadController {

    @Autowired
    private FileUtil fileUtil;

    /**
     * 本地文件上传(通用版)
     * @param file 上传的文件
     * @param fileType 文件类型(common:普通文件,excel:Excel文件,image:图片文件)
     * @return 上传结果(存储路径、访问URL等)
     */
    @PostMapping("/upload")
    public ResponseEntity<Map<String, Object>> uploadFile(
            @RequestParam("file") MultipartFile file,
            @RequestParam("fileType") String fileType) {

        Map&lt;String, Object&gt; result = new HashMap<>();
        try {
            // 1. 校验文件类型参数
            String targetDir = getTargetDirByFileType(fileType);
            // 2. 上传文件,获取物理存储路径
            String physicalPath = fileUtil.uploadFile(file, targetDir);
            // 3. 拼接返回结果
            result.put("code", 200);
            result.put("message", "文件上传成功");
            result.put("physicalPath", physicalPath); // 本地物理路径
            result.put("fileName", file.getOriginalFilename()); // 原始文件名
            // 图片文件额外返回访问URL
            if ("image".equals(fileType)) {
                String uniqueFileName = physicalPath.substring(physicalPath.lastIndexOf(File.separator) + 1);
                result.put("accessUrl", fileUtil.getImageAccessUrl(uniqueFileName));
            }
            return ResponseEntity.ok(result);
        } catch (IOException e) {
            result.put("code", 500);
            result.put("message", "文件上传失败:" + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
        }
    }

    /**
     * 根据文件类型获取目标存储目录
     */
    private String getTargetDirByFileType(String fileType) {
        switch (fileType) {
            case "excel":
                return fileUtil.getExcelUploadPath();
            case "image":
                return fileUtil.getCommonUploadPath() + "images/";
            default:
                return fileUtil.getCommonUploadPath();
        }
    }
}

2.2 接口测试(Postman)

  1. 请求方式:POST,接口地址:http://localhost:8080/file/upload

  2. 请求参数:

    • file:选择要上传的文件(如文档、压缩包)

    • fileType:传入common(普通文件)

  3. 响应结果(成功):

{
  "code": 200,
  "message": "文件上传成功",
  "physicalPath": "D:/springboot-file/upload/common/xxx.jpg",
  "fileName": "test.jpg"
}

验证:打开配置的本地存储目录,可看到上传的文件(文件名已转为UUID格式,避免重复)。

三、核心实战二:图片上传与回显

图片上传是最常用的场景(如头像、商品图片),相比普通文件,核心多了「图片格式校验」「图片回显」两个关键点,可选做图片压缩(优化存储大小)。

3.1 图片上传优化(新增图片校验与压缩)

在通用工具类基础上,新增图片专属方法,校验图片格式(仅允许jpg、png、jpeg),并通过thumbnailator实现图片压缩:

// 在FileUtil类中新增以下方法
import net.coobird.thumbnailator.Thumbnails;

/**
 * 校验图片格式(仅允许jpg、png、jpeg)
 * @param originalFilename 原始文件名
 * @throws IOException 格式不合法时抛出异常
 */
public void validateImageFormat(String originalFilename) throws IOException {
    String suffix = FilenameUtils.getExtension(originalFilename).toLowerCase();
    if (!"jpg".equals(suffix) && !"png".equals(suffix) && !"jpeg".equals(suffix)) {
        throw new IOException("图片格式不合法,仅支持jpg、png、jpeg格式");
    }
}

/**
 * 图片上传(带格式校验+压缩)
 * @param file 图片文件
 * @param width 压缩后宽度(0表示不限制宽度,按比例缩放)
 * @param height 压缩后高度(0表示不限制高度,按比例缩放)
 * @return 图片存储路径+访问URL
 */
public Map<String, String> uploadImage(MultipartFile file, int width, int height) throws IOException {
    // 1. 校验图片格式
    validateImageFormat(file.getOriginalFilename());
    // 2. 校验文件大小(可额外添加,如限制图片不超过5MB)
    long fileSize = file.getSize();
    if (fileSize > 5 * 1024 * 1024) {
        throw new IOException("图片大小不能超过5MB");
    }
    // 3. 生成唯一文件名
    String uniqueFileName = generateUniqueFileName(file.getOriginalFilename());
    // 4. 目标存储目录(单独划分图片目录)
    String imageDir = commonUploadPath + "images/";
    createDirectory(imageDir);
    // 5. 图片压缩并上传
    String physicalPath = imageDir + File.separator + uniqueFileName;
    Thumbnails.of(file.getInputStream())
            .size(width, height) // 压缩尺寸,0表示按比例缩放
            .outputQuality(0.8) // 压缩质量(0.0-1.0),0.8表示保留80%质量
            .toFile(physicalPath);
    // 6. 组装结果(存储路径+访问URL)
    Map<String, String&gt; result = new HashMap<>();
    result.put("physicalPath", physicalPath);
    result.put("accessUrl", getImageAccessUrl(uniqueFileName));
    return result;
}

3.2 图片上传接口(Controller)

新增图片专属上传接口,支持压缩参数配置,方便前端根据需求调整图片尺寸:

// 在FileUploadController中新增接口
/**
 * 图片上传(带格式校验+压缩)
 * @param file 图片文件
 * @param width 压缩后宽度(默认0,按比例缩放)
 * @param height 压缩后高度(默认0,按比例缩放)
 * @return 上传结果
 */
@PostMapping("/upload/image")
public ResponseEntity<Map<String, Object>> uploadImage(
        @RequestParam("file") MultipartFile file,
        @RequestParam(defaultValue = "0") int width,
        @RequestParam(defaultValue = "0") int height) {

    Map<String, Object> result = new HashMap<>();
    try {
        // 调用图片上传方法
        Map<String, String> imageInfo = fileUtil.uploadImage(file, width, height);
        result.put("code", 200);
        result.put("message", "图片上传成功");
        result.put("imageInfo", imageInfo);
        return ResponseEntity.ok(result);
    } catch (IOException e) {
        result.put("code", 500);
        result.put("message", "图片上传失败:" + e.getMessage());
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
    }
}

3.3 图片回显实现

核心依赖前面application.yml中的静态资源配置,无需额外编写接口,直接通过返回的accessUrl即可访问图片。

  1. 上传图片后,获取响应中的accessUrl(如:/upload/images/xxx.jpg);

  2. 拼接完整访问地址:http://localhost:8080 + accessUrl(如:http://localhost:8080/upload/images/xxx.jpg);

  3. 在浏览器或前端页面直接访问该URL,即可回显图片。

注意:若回显失败,检查3点:① 静态资源配置是否正确(static-locations是否指向本地存储路径);② 图片物理路径是否正确生成;③ 访问URL是否拼接完整(端口、路径是否正确)。

四、核心实战三:Excel 文件上传解析(POI + EasyExcel)

Excel上传解析是小工具开发的核心(如数据导入),本文分别实现POI和EasyExcel两种方式,POI适合复杂Excel(合并单元格、公式),EasyExcel适合大数据量、简单Excel,按需选择。

先准备测试Excel:创建user.xlsx,表头为「用户名、手机号、角色」,填入几条测试数据。

4.1 基础准备:Excel 实体类(DTO)

定义与Excel表头对应的实体类,用于接收解析后的数据:

import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;

/**
 * Excel解析实体类(与Excel表头对应)
 * 注解说明:@ExcelProperty用于EasyExcel,value对应表头名称,index对应列索引
 */
@Data
public class ExcelUserDTO {

    @ExcelProperty(value = "用户名", index = 0)
    private String username;

    @ExcelProperty(value = "手机号", index = 1)
    private String phone;

    @ExcelProperty(value = "角色", index = 2)
    private String role;
}

4.2 方式一:POI 实现 Excel 上传解析

POI是Apache的开源组件,兼容性强,可处理复杂Excel,但内存占用较高,适合小数据量Excel解析。

4.2.1 POI 解析工具类
import com.example.demo.dto.ExcelUserDTO;
import org.apache.poi.ss.usermodel.*;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * POI Excel解析工具类
 */
@Component
public class PoiExcelUtil {

    /**
     * 解析Excel文件(.xlsx、.xls)
     * @param file Excel文件
     * @return 解析后的用户列表
     */
    public List<ExcelUserDTO> parseExcel(MultipartFile file) throws IOException {
        List<ExcelUserDTO> userList = new ArrayList<>();
        // 1. 获取文件输入流
        try (InputStream inputStream = file.getInputStream()) {
            // 2. 根据文件后缀创建Workbook(.xlsx用XSSFWorkbook,.xls用HSSFWorkbook)
            Workbook workbook = WorkbookFactory.create(inputStream);
            // 3. 获取第一个工作表(默认读取第一个sheet)
            Sheet sheet = workbook.getSheetAt(0);
            if (sheet == null) {
                throw new IOException("Excel文件中无工作表");
            }
            // 4. 跳过表头(第0行是表头,从第1行开始读取数据)
            int rowNum = sheet.getLastRowNum(); // 最后一行的索引(从0开始)
            for (int i = 1; i <= rowNum; i++) {
                Row row = sheet.getRow(i);
                if (row == null) {
                    continue; // 跳过空行
                }
                // 5. 读取每一列数据,封装到DTO
                ExcelUserDTO userDTO = new ExcelUserDTO();
                // 用户名(第0列)
                Cell usernameCell = row.getCell(0);
                userDTO.setUsername(getCellValue(usernameCell));
                // 手机号(第1列)
                Cell phoneCell = row.getCell(1);
                userDTO.setPhone(getCellValue(phoneCell));
                // 角色(第2列)
                Cell roleCell = row.getCell(2);
                userDTO.setRole(getCellValue(roleCell));
                // 6. 添加到列表
                userList.add(userDTO);
            }
            // 7. 关闭资源
            workbook.close();
        }
        return userList;
    }

    /**
     * 获取单元格的值(兼容不同单元格类型:字符串、数字等)
     */
    private String getCellValue(Cell cell) {
        if (cell == null) {
            return "";
        }
        // 设置单元格类型为字符串,避免数字自动转为科学计数法
        cell.setCellType(CellType.STRING);
        return cell.getStringCellValue().trim();
    }
}
4.2.2 POI 解析接口(Controller)
// 在FileUploadController中新增接口
@Autowired
private PoiExcelUtil poiExcelUtil;

/**
 * POI 解析Excel文件
 * @param file Excel文件(.xlsx、.xls)
 * @return 解析结果
 */
@PostMapping("/upload/excel/poi")
public ResponseEntity<Map<String, Object>> parseExcelByPoi(@RequestParam("file") MultipartFile file) {
    Map&lt;String, Object&gt; result = new HashMap<>();
    try {
        // 1. 校验文件格式(仅允许xlsx、xls)
        String suffix = FilenameUtils.getExtension(file.getOriginalFilename()).toLowerCase();
        if (!"xlsx".equals(suffix) && !"xls".equals(suffix)) {
            result.put("code", 400);
            result.put("message", "文件格式不合法,仅支持.xlsx、.xls格式");
            return ResponseEntity.badRequest().body(result);
        }
        // 2. 上传Excel文件(先存储到本地,可选)
        String physicalPath = fileUtil.uploadFile(file, fileUtil.getExcelUploadPath());
        // 3. 解析Excel
        List<ExcelUserDTO> userList = poiExcelUtil.parseExcel(file);
        // 4. 组装结果(可后续将解析的数据存入数据库)
        result.put("code", 200);
        result.put("message", "Excel解析成功");
        result.put("filePath", physicalPath);
        result.put("dataCount", userList.size());
        result.put("data", userList);
        return ResponseEntity.ok(result);
    } catch (IOException e) {
        result.put("code", 500);
        result.put("message", "Excel解析失败:" + e.getMessage());
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
    }
}

4.3 方式二:EasyExcel 实现 Excel 上传解析

EasyExcel是阿里巴巴开源的Excel解析工具,内存占用极低(避免OOM),API简洁,适合大数据量Excel解析,推荐使用。

4.3.1 EasyExcel 监听器(核心)

EasyExcel采用监听器模式解析Excel,需自定义监听器,处理解析后的每一行数据:

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.example.demo.dto.ExcelUserDTO;
import lombok.Getter;
import java.util.ArrayList;
import java.util.List;

/**
 * EasyExcel 解析监听器(监听每一行数据的解析)
 */
@Getter // 提供getter方法,获取解析后的列表
public class ExcelUserListener extends AnalysisEventListener<ExcelUserDTO> {

    // 存储解析后的用户数据
    private List&lt;ExcelUserDTO&gt; userList = new ArrayList<>();

    /**
     * 每解析一行数据,就会调用该方法
     * @param data 解析后的一行数据(与ExcelUserDTO对应)
     * @param context 解析上下文
     */
    @Override
    public void invoke(ExcelUserDTO data, AnalysisContext context) {
        // 校验数据(可选,如非空校验)
        if (data.getUsername() == null || data.getUsername().trim().isEmpty()) {
            throw new RuntimeException("第" + (context.readRowHolder().getRowIndex() + 1) + "行,用户名为空");
        }
        // 将数据添加到列表
        userList.add(data);
    }

    /**
     * 解析完成后,调用该方法(可做后续处理,如存入数据库)
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        System.out.println("Excel解析完成,共解析" + userList.size() + "条数据");
    }
}
4.3.2 EasyExcel 解析接口(Controller)
// 在FileUploadController中新增接口
import com.alibaba.excel.EasyExcel;

/**
 * EasyExcel 解析Excel文件(推荐,轻量高效)
 * @param file Excel文件(.xlsx、.xls)
 * @return 解析结果
 */
@PostMapping("/upload/excel/easyexcel")
public ResponseEntity<Map<String, Object>> parseExcelByEasyExcel(@RequestParam("file") MultipartFile file) {
    Map<String, Object> result = new HashMap<>();
    try {
        // 1. 校验文件格式
        String suffix = FilenameUtils.getExtension(file.getOriginalFilename()).toLowerCase();
        if (!"xlsx".equals(suffix) && !"xls".equals(suffix)) {
            result.put("code", 400);
            result.put("message", "文件格式不合法,仅支持.xlsx、.xls格式");
            return ResponseEntity.badRequest().body(result);
        }
        // 2. 上传Excel文件(可选)
        String physicalPath = fileUtil.uploadFile(file, fileUtil.getExcelUploadPath());
        // 3. 初始化监听器
        ExcelUserListener listener = new ExcelUserListener();
        // 4. 解析Excel(无需创建Workbook,EasyExcel自动处理)
        EasyExcel.read(file.getInputStream(), ExcelUserDTO.class, listener)
                .sheet() // 读取第一个sheet
                .headRowNumber(1) // 表头行数(1表示第0行是表头,从第1行开始读取数据)
                .doRead();
        // 5. 获取解析后的数据
        List<ExcelUserDTO> userList = listener.getUserList();
        // 6. 组装结果
        result.put("code", 200);
        result.put("message", "Excel解析成功");
        result.put("filePath", physicalPath);
        result.put("dataCount", userList.size());
        result.put("data", userList);
        return ResponseEntity.ok(result);
    } catch (Exception e) {
        result.put("code", 500);
        result.put("message", "Excel解析失败:" + e.getMessage());
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
    }
}

4.4 POI 与 EasyExcel 对比(选型建议)

对比维度POIEasyExcel
内存占用较高,容易OOM(大数据量时)极低,基于Sax解析,无内存压力
API复杂度较复杂,需手动处理Workbook、Sheet、Row、Cell简洁,通过监听器+注解即可完成解析
复杂Excel支持支持(合并单元格、公式、图表等)支持基础复杂场景,高级场景需额外处理
适用场景小数据量、复杂Excel解析大数据量、简单Excel解析(推荐日常开发)

五、常见问题与解决方案

  1. 文件上传失败,提示“文件过大”?

         解决方案:修改application.yml中spring.servlet.multipart.max-file-size和max-request-size的值,单位支持MB、KB,如10MB、50MB。
    
  2. 图片回显404?

         解决方案:① 检查静态资源配置(static-locations是否正确指向本地存储路径,如file:D:/xxx/);② 确认图片物理路径是否正确生成,文件是否存在;③ 访问URL是否拼接完整(如端口是否正确)。
    
  3. Excel解析时,数字自动转为科学计数法?

         解决方案:POI中通过cell.setCellType(CellType.STRING)将单元格转为字符串类型;EasyExcel中在实体类字段添加@ExcelProperty(converter = StringConverter.class),自定义转换器。
    
  4. EasyExcel解析时,表头与实体类不匹配?

         解决方案:确保@ExcelProperty的value与Excel表头完全一致(大小写、空格都要匹配),或通过index指定列索引(更稳妥)。
    
  5. 文件上传路径中文乱码?

         解决方案:存储路径尽量使用英文路径,避免中文;若必须使用中文,需在配置文件中对路径进行编码,或在代码中处理编码问题。
    

六、总结

本文承接纯接口开发的基础,完整实战了Spring Boot文件操作的核心场景——本地文件上传、图片上传与回显、Excel上传解析(POI+EasyExcel),覆盖小工具开发的核心需求,核心要点:

  • 本地文件上传:核心是生成唯一文件名、创建存储目录、校验文件合法性,通用适配所有文件类型。

  • 图片上传:额外增加格式校验、图片压缩,通过静态资源配置实现图片回显,贴合实际开发场景。

  • Excel解析:POI适合复杂场景,EasyExcel适合大数据量,按需选择,核心是将Excel数据映射为实体类,便于后续业务处理。

掌握本文内容后,可轻松实现图片上传、Excel导入等小工具核心功能,后续可进一步扩展:文件下载、文件删除、云存储(如阿里云OSS)集成等,让文件操作功能更完善,适配更多实际开发需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码客日记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值