Spring MVC文件上传:commons-fileupload解析全流程

🧩 一、整体上传流程(Spring MVC + commons-fileupload)

当用户通过浏览器上传文件(如 <form enctype="multipart/form-data">)时,整个流程如下:

复制代码
[浏览器] 
   ↓ (HTTP POST with multipart/form-data)
[Servlet 容器(如 Tomcat)]
   ↓ (原始 HttpServletRequest)
[Spring DispatcherServlet]
   ↓ (检测到 multipart 请求)
[CommonsMultipartResolver]
   ↓ (调用 commons-fileupload 解析请求体)
[生成 CommonsMultipartFile 对象]
   ↓ (注入到 Controller 方法参数或自定义 Bean 中)
[你的业务代码:importValuation(FileUpLoadBean file)]

⏱️ 二、commons-fileupload 在哪个阶段起作用?

✅ 关键阶段:请求解析阶段(在 Controller 执行之前)

具体来说:

  1. DispatcherServlet 收到请求

    判断 Content-Type 是否为 multipart/form-data

  2. 调用 MultipartResolver

    如果配置了 CommonsMultipartResolver,Spring 会委托它处理该请求。

  3. CommonsMultipartResolver 内部使用 commons-fileupload

    • 调用 ServletFileUpload.parseRequest(request)(来自 commons-fileupload 库)
    • 将原始字节流解析为一个个 FileItem(代表每个表单项,包括文件和普通字段)
    • 把文件类型的 FileItem 封装成 CommonsMultipartFile 对象
  4. 替换原始 Request

    Spring 会把原始的 HttpServletRequest 包装成 MultipartHttpServletRequest,其中包含解析好的文件和参数。

  5. Controller 方法被调用

    Spring 通过数据绑定(Data Binding),将 MultipartHttpServletRequest 中的文件自动赋值给你的 FileUpLoadBean.file 字段(类型为 CommonsMultipartFile)。

🔍 所以,commons-fileupload 的作用发生在 Controller 执行之前,是"幕后解析者"


🛠️ 三、commons-fileupload 的核心作用是什么?

commons-fileupload 是 Apache 提供的一个 通用的 multipart/form-data 请求解析库。它的主要职责是:

功能 说明
解析 HTTP multipart 请求体 将原始字节流按 RFC 1867 标准拆分为多个"项"(FileItem)
区分普通字段和文件字段 比如 <input name="username"><input type="file" name="file">
处理大文件上传 支持内存/磁盘混合存储(通过 DiskFileItemFactory
提供流式读取 可以通过 getInputStream() 逐块读取文件内容,避免 OOM
支持文件名、ContentType 等元信息提取 getName(), getContentType(), getSize()

💡 注意:commons-fileupload 本身与 Spring 无关 ,它是一个独立的工具库。

Spring 只是封装 了它,通过 CommonsMultipartResolverCommonsMultipartFile 使其融入 MVC 框架。


📦 四、关键类关系图(简化)

text 复制代码
commons-fileupload 库:
  └── ServletFileUpload
        └── parseRequest() → List<FileItem>
              └── FileItem (代表一个表单项)
                    ├── isFormField() → true/false
                    ├── getName()      → 字段名(如 "file")
                    ├── getString()    → 普通字段值
                    └── getInputStream() → 文件内容流

Spring 封装层:
  └── CommonsMultipartResolver
        └── 使用 ServletFileUpload 解析请求
        └── 将 FileItem → CommonsMultipartFile
              └── getFileItem() → 返回底层 FileItem
              └── getInputStream() → 代理调用 FileItem.getInputStream()

🧪 五、你项目中的具体体现

  • 你配置了 CommonsMultipartResolver → 启用 commons-fileupload 解析。
  • 你使用 CommonsMultipartFile → 直接暴露了底层实现。
  • 当用户 POST 到 /importValuation.action 时:
    • commons-fileupload 已经在进入方法前完成了文件解析;
    • file.getFile() 返回的就是它解析出的文件对象;
    • 你可以安全地调用 .isEmpty(), .getInputStream(), .getOriginalFilename() 等方法。

🆚 对比:不用 commons-fileupload 的情况(Servlet 3.0+)

如果使用 StandardServletMultipartResolver(Spring Boot 默认):

  • 不需要 commons-fileupload 依赖;
  • 文件类型是 StandardMultipartFile
  • 解析工作由 Servlet 容器(如 Tomcat) 完成;
  • 功能类似,但配置方式不同(通过 multipart-configapplication.properties)。

✅ 总结

问题 回答
整个流程? 浏览器 → Servlet 容器 → Spring → CommonsMultipartResolvercommons-fileupload 解析 → 生成 CommonsMultipartFile → 注入 Controller
在哪个阶段起作用? Controller 执行之前 ,在 Spring 的请求预处理阶段(由 DispatcherServlet 触发)
作用是什么? 解析 multipart/form-data 请求体,将原始 HTTP 流转换为结构化的文件和字段对象

如果你后续想优化性能(如限制内存使用、支持大文件分片)、或迁移到更现代的方案(如 Spring Boot + Servlet 3.0+),也可以继续问我!

相关推荐
一 乐6 分钟前
自习室座位预约管理系统|基于springboot + vue自习室座位预约管理系统(源码+数据库+文档)
java·vue.js·spring boot
此时不提桶,更待何时25 分钟前
02-02-B-AQS与JUC锁面试与生产事故实战
java
音符犹如代码28 分钟前
Kafka 接入 AI 的三条路线:MCP 提案、会话记忆与实时上下文
java·大数据·ai·kafka
vx_BS8133032 分钟前
【项目编号:project51629】Spring Boot 乡村自来水缴费系统:把抄表、水费生成与在线缴费做成一条数字化闭环
java·spring boot·eclipse·tomcat·maven
qq_2695067540 分钟前
第29课-Servlet基础
java
毅炼1 小时前
不写多语言 SDK,怎么让 Python、Go、Node 服务接入注册中心?
java·后端·系统架构·gateway
2501_937860941 小时前
上篇:网络编程基础与UDP套接字编程
java·网络·计算机网络
泡海椒1 小时前
jquick-pdf 表格行列尺寸控制实战:单元格合并的可行边界
java·开发语言·pdf
Wang's Blog1 小时前
Java 项目实战: 外卖平台-后台系统登录功能开发
java·服务器·redis
海鸥-w1 小时前
spingboot定义一个全局异常处理器
java