Java文件传输利器:MultipartFile介绍

目录

[一、MultipartFile 是什么?](#一、MultipartFile 是什么?)

二、核心方法详解

[1. getOriginalFilename()](#1. getOriginalFilename())

[2. getInputStream()](#2. getInputStream())

[3. transferTo](#3. transferTo)

[三、Spring 是如何处理文件上传的?](#三、Spring 是如何处理文件上传的?)

[1. 前端发送 multipart 请求](#1. 前端发送 multipart 请求)

[2. Spring 解析请求](#2. Spring 解析请求)

[3. 转换为 MultipartFile](#3. 转换为 MultipartFile)

[四、最小可运行 Demo](#四、最小可运行 Demo)

[1. Controller 示例](#1. Controller 示例)

[2. curl 测试](#2. curl 测试)

[3. 配置文件](#3. 配置文件)

五、大文件处理与流式上传

[1 错误写法](#1 错误写法)

[2 正确写法](#2 正确写法)

[3 示例](#3 示例)

六、常见坑总结

[1. 文件名安全问题(路径穿越)](#1. 文件名安全问题(路径穿越))

[2. 文件类型伪造](#2. 文件类型伪造)

[3. 临时文件问题](#3. 临时文件问题)

[4. 大文件限制](#4. 大文件限制)


在日常开发中,文件传输几乎是一个"必备能力":头像上传、Excel导入、日志收集......而在 Spring Boot 体系中,处理文件上传的核心接口就是 MultipartFile

一、MultipartFile 是什么?

MultipartFile 是 Spring 提供的一个接口,用于表示 HTTP 请求中上传的文件。当浏览器使用 multipart/form-data 提交表单时,例如:

复制代码
POST /upload
Content-Type: multipart/form-data

Spring 会自动将请求解析,并把文件部分封装为 MultipartFile 对象。

可以理解为:

MultipartFile 是"上传文件在服务端的抽象表示"

二、核心方法详解

MultipartFile 提供了一组非常实用的方法:

复制代码
public interface MultipartFile {
    String getName();
    String getOriginalFilename();
    String getContentType();
    boolean isEmpty();
    long getSize();
    byte[] getBytes() throws IOException;
    InputStream getInputStream() throws IOException;
    void transferTo(File dest) throws IOException, IllegalStateException;
    
    default Resource getResource() {
        return new MultipartFileResource(this);
    }
    default void transferTo(Path dest) throws IOException, IllegalStateException {
        FileCopyUtils.copy(this.getInputStream(), Files.newOutputStream(dest));
    }
}

1. getOriginalFilename()

复制代码
String filename = file.getOriginalFilename();
  • 获取上传时的文件名

  • 注意:不安全,可能被伪造

2. getInputStream()

复制代码
InputStream in = file.getInputStream();

适用于:

  • 上传到 HDFS / OSS / S3

  • 流式处理(避免大文件内存问题)

3. transferTo

复制代码
file.transferTo(new File("/data/upload/test.txt"));

特点:

  • 内部已优化(可能使用零拷贝)

  • 性能优于手动写流

  • 使用最简单

一句话:保存文件优先用它

三、Spring 是如何处理文件上传的?

很多人只会用,不知道背后发生了什么。整个流程如下:

1. 前端发送 multipart 请求

复制代码
<form method="post" enctype="multipart/form-data">
    <input type="file" name="file"/>
</form>

2. Spring 解析请求

核心组件:

  • MultipartResolver

默认实现:

  • StandardServletMultipartResolver

3. 转换为 MultipartFile

Spring 会:

  • 解析 HTTP Body

  • 提取文件部分

  • 封装为 MultipartFile

  • 注入 Controller 参数

四、最小可运行 Demo

1. Controller 示例

复制代码
@RestController
@RequestMapping("/file")
public class FileUploadController {
​
    @PostMapping("/upload")
    public String upload(@RequestParam("file") MultipartFile file) {
​
        if (file.isEmpty()) {
            return "文件为空";
        }
​
        try {
            String filename = file.getOriginalFilename();
            File dest = new File("D:/upload/" + filename);
​
            file.transferTo(dest);
​
            return "上传成功:" + filename;
        } catch (Exception e) {
            e.printStackTrace();
            return "上传失败";
        }
    }
}

2. curl 测试

复制代码
curl -X POST "http://localhost:8080/file/upload" \
  -H "Content-Type: multipart/form-data" \
  -F "file=@D:/test/a.txt"

3. 配置文件

复制代码
spring:
  servlet:
    multipart:
      max-file-size: 100MB
      max-request-size: 100MB

五、大文件处理与流式上传

1 错误写法

复制代码
byte[] data = file.getBytes();

问题:

  • 文件越大,占用内存越高

  • 容易 OOM

2 正确写法

复制代码
try (InputStream in = file.getInputStream()) {
    // 流式处理
}

3 示例

复制代码
public void uploadToHdfs(MultipartFile file) throws Exception {
​
    FileSystem fs = FileSystem.get(new Configuration());
​
    Path path = new Path("/data/" + file.getOriginalFilename());
​
    try (FSDataOutputStream out = fs.create(path);
         InputStream in = file.getInputStream()) {
​
        byte[] buffer = new byte[1024];
        int len;
​
        while ((len = in.read(buffer)) != -1) {
            out.write(buffer, 0, len);
        }
    }
}

六、常见坑总结

1. 文件名安全问题(路径穿越)

错误写法:

复制代码
new File("/upload/" + file.getOriginalFilename());

攻击方式:

复制代码
../../../../etc/passwd

正确写法:

复制代码
String filename = Paths.get(file.getOriginalFilename()).getFileName().toString();

2. 文件类型伪造

复制代码
file.getContentType()

不可靠!

建议:

  • 校验文件头(magic number)

  • 或白名单限制

3. 临时文件问题

Spring 机制:

  • 小文件 → 内存

  • 大文件 → 临时磁盘

默认路径:

复制代码
/tmp 或 Tomcat temp

4. 大文件限制

如果没配置,会报错:

复制代码
MaxUploadSizeExceededException
相关推荐
Java.熵减码农2 小时前
经典20道Java面试题系列(一)
java·开发语言
yhole2 小时前
Spring Boot整合Redisson的两种方式
java·spring boot·后端
sthnyph2 小时前
Spring Boot 集成 Kettle
java·spring boot·后端
MyBFuture2 小时前
Halcon 图像处理技巧:抠图与形态学操作指南
开发语言·halcon
sxhcwgcy2 小时前
Spring.factories
java·数据库·spring
Mike117.2 小时前
GBase 8a 数据同步实践:从 T+1 同步、实时镜像到一写多读的落地思路
java·服务器·数据库
qq_416018722 小时前
移动平台C++开发指南
开发语言·c++·算法
Nyarlathotep01132 小时前
LongAdder为什么那么快?
java·后端
自动化智库2 小时前
西门子S7-1200PLC与V90PN伺服基于FB284模块的定位控制应用
开发语言·科技