Java 文件上传的“血泪进化史”:从 Servlet 哭着写到 SSM 笑着传,到底有几种姿势?
文件上传是 Java Web 的“入门仪式”,它能把你虐得死去活来,也能让你瞬间开窍。
今天咱们就从远古时代(Servlet)一路聊到现代文明(SSM/SpringBoot),看看这玩意儿到底进化出了几种姿势。
第一种姿势:Apache Commons FileUpload(远古巨兽级,手动挡开坦克)
年代:2005年左右~至今(老项目还在用,兼容性满分)
核心武器:commons-fileupload + commons-io 两个 jar 包
典型代码(准备好纸巾,这段能把你看哭):
Java
// 1. 创建工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
// 2. 创建解析器
ServletFileUpload upload = new ServletFileUpload(factory);
// 3. 解析请求(这一步最容易爆内存)
List<FileItem> items = upload.parseRequest(request);
// 4. 手动遍历,一个一个判断是普通表单还是文件
for (FileItem item : items) {
if (item.isFormField()) {
// 普通表单字段
String value = item.getString("UTF-8");
} else {
// 文件!终于等到你!
InputStream in = item.getInputStream();
FileOutputStream out = new FileOutputStream("/upload/" + item.getName());
IOUtils.copy(in, out); // 还得自己拷贝流...
item.delete(); // 记得删临时文件,不然磁盘炸了
}
}
优点:能跑!哪儿都能跑!连 Tomcat 5 都能跑! 缺点:代码量感人,还得自己判断是文件还是普通字段,临时文件还得自己删,稍微不注意就 OOM。
评价:这就像手动挡拖拉机,油门离合全靠手,新手十个有九个熄火,剩下一个直接翻车。
第二种姿势:Servlet 3.0+ 原生 Part API(国家终于出手了)
年代:2010年以后(Tomcat 7+ 开始支持)
核心武器:零依赖!只要在 Servlet 上加一个注解就行!
Java
@WebServlet("/upload")
@MultipartConfig( // ← 这行注解是灵魂!
location = "/tmp",
maxFileSize = 1024*1024*10, // 单文件最大10M
maxRequestSize = 1024*1024*50 // 总请求最大50M
)
public class UploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
Part part = request.getPart("file"); // 直接拿!
String fileName = getSubmittedFileName(part); // 自己写个工具方法提取文件名
part.write("/upload/" + fileName); // 一行存文件!爽!
}
}
优点:
- 零 jar 包,原生支持
- 性能最好(官方实现的还能有假?)
- part.write() 一行存文件,优雅得我哭了
缺点:
- 必须在 Servlet 上加 @MultipartConfig,忘了就寄
- 获取文件名还得自己写工具方法(浏览器不同实现不一样)
- 多文件要 request.getParts() 自己遍历
评价:这就像从拖拉机换成了自动挡桑塔纳,虽然车身还是有点硬,但至少不用老踩离合了!
第三种姿势:SpringMVC 的 MultipartFile(现代文明,自动挡豪车)
年代:2012年以后(SSM 项目99%都在用这个)
核心武器:Spring 内置的两种解析器(你根本不用管底层是啥)
最优雅代码(准备尖叫):
Java
@PostMapping("/upload")
public String upload(@RequestParam("file") MultipartFile file) {
if (!file.isEmpty()) {
file.transferTo(new File("/upload/" + file.getOriginalFilename()));
// 一行搞定!连流都不用管!
}
return "success";
}
// 多文件?更简单!
@PostMapping("/batch")
public String batch(@RequestParam("files") MultipartFile[] files) {
for (MultipartFile file : files) {
file.transferTo(...);
}
}
Spring 还偷偷帮你干了这些事:
- 自动判断是不是 multipart 请求
- 自动创建临时文件
- 自动删除临时文件
- 自动限流限大小(配置文件里写两行就行)
- SpringBoot 甚至连配置都给你省了!
评价:这就像特斯拉自动驾驶,你只管说“上传”,剩下的它全给你安排得明明白白。 我现在写文件上传就两行代码,领导看了直呼内行。
真相揭秘:其实底层就两种解析器!
很多人以为有三种,其实 SpringMVC 偷偷把前两种都封装了:
| Spring 的解析器类 | 底层实际用的是 | 什么时候用 |
|---|---|---|
| CommonsMultipartResolver | 第一种(Commons FileUpload) | 老项目、SpringBoot 1.x 默认 |
| StandardServletMultipartResolver | 第二种(Servlet 3.0 Part) | SpringBoot 2.x+ 默认(推荐!) |
所以你写 MultipartFile 的时候,SpringBoot 其实在背后默默用了 Servlet 3.0 的 Part,性能拉满!
2025 年了,你还用哪种?
- 新项目/SpringBoot:直接 MultipartFile,连想都别想别的!
- 老项目升级不了:用 Part API,至少别再写 Commons 了
- 博物馆级古董项目:Commons FileUpload(看到请默哀三秒)
总结(金句送给你们)
“文件上传的最高境界,就是让别人看不出你写了文件上传。”
从 200 行哭着敲,到现在 2 行笑着传。 这,就是 Java Web 的成长!
喜欢记得点赞收藏评论转发。
更多推荐



所有评论(0)