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
相关推荐
dllxhcjla17 小时前
微服务全套
java
亚历克斯神17 小时前
JVM 内存管理 2026:深度解析与调优实战
java·spring·微服务
以神为界17 小时前
Python入门实操:基础语法+爬虫入门+模块使用全指南
开发语言·网络·爬虫·python·安全·web
逻辑驱动的ken18 小时前
Java高频面试题:03
java·开发语言·面试·求职招聘·春招
噜噜大王_18 小时前
深入理解 C 语言内存操作函数:memcpy、memmove、memset、memcmp
c语言·开发语言
广师大-Wzx18 小时前
一篇文章看懂MySQL数据库(下)
java·开发语言·数据结构·数据库·windows·python·mysql
野生技术架构师18 小时前
Java NIO到底是个什么东西?
java·开发语言·nio
lolo大魔王19 小时前
Go语言的异常处理
开发语言·后端·golang
likerhood19 小时前
简单工厂设计模式
java·ide·intellij-idea
chh56319 小时前
C++--模版初阶
c语言·开发语言·c++·学习·算法