ServletFileUpload.parseRequest()返回空列表主因是请求体未被识别为multipart/form-data,常见于前端漏设enctype、Fetch/Axios未让浏览器自动生成Content-Type、Spring Boot未启用multipart解析或Servlet配置禁用multipart支持。

为什么 ServletFileUpload.parseRequest() 总是返回空列表?
不是文件没传,而是请求体没被正确识别为 multipart/form-data。常见原因是前端表单漏了 enctype="multipart/form-data",或者用 Fetch/Axios 上传时没设 Content-Type(其实不该手动设,让浏览器自动生成 boundary)。
另一个隐蔽坑:Spring Boot 默认禁用 multipart 解析,如果项目用了 Spring,得确认 spring.servlet.multipart.enabled=true(2.0+ 版本)且没被覆盖。纯 Servlet 环境则必须确保 web.xml 或 @WebServlet 配置里没禁用 multipart 支持。
- 检查请求头是否含
Content-Type: multipart/form-data; boundary=... - 用浏览器开发者工具的 Network → Payload 查看原始请求体,确认有
------WebKitFormBoundary...分隔符 -
ServletFileUpload.isMultipartContent(request)必须返回true才能继续解析
下载时 Content-Disposition 头中文文件名乱码怎么办?
根本原因:HTTP 响应头不支持 UTF-8 直接编码,RFC 5987 规定要用 filename*=UTF-8''xxx 格式。直接写 filename="中文.txt" 在 Chrome/Firefox 下大概率显示为 %E4%B8%AD%E6%96%87.txt。
Java 中别手拼字符串,用 URLEncoder.encode() 只编码文件名部分,并加上 UTF-8'' 前缀。注意:IE 旧版只认 filename(不带星号),所以得兼容双写。
立即学习“Java免费学习笔记(深入)”;
- 推荐写法:
response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(filename, "UTF-8").replace("+", "%20") + "\"; filename*=UTF-8''" + URLEncoder.encode(filename, "UTF-8")); - 避免用
new String(filename.getBytes("ISO-8859-1"), "UTF-8")这类“骗浏览器”的老办法,现代浏览器已不买账 - 如果文件名来自用户输入,务必先校验或清理路径遍历字符(如
../)
用 DiskFileItemFactory 时临时文件占满磁盘怎么防?
默认行为是:小文件内存缓存,大文件写入临时目录(java.io.tmpdir)。一旦并发上传多、单个文件大、或没及时清理,/tmp 很快爆掉——而且这些文件不会自动删除。
关键控制点就三个参数:sizeThreshold(内存阈值)、repository(临时目录)、fileSizeMax(单文件上限)。不设 repository 就用系统默认 tmp,极难监控;不设 fileSizeMax 可能被恶意传入超大文件拖垮服务。
- 显式指定临时目录:
factory.setRepository(new File("/path/to/upload-tmp")),并确保该路径有写权限且独立于系统 tmp - 设合理阈值:
factory.setSizeThreshold(1024 * 1024)(1MB),避免小文件全进磁盘 - 务必配合
upload.setFileSizeMax(100 * 1024 * 1024)和upload.setSizeMax(...)做总大小限制
Spring MVC 里还该手动用 Apache Commons FileUpload 吗?
不该。Spring 自带 MultipartFile 抽象已经封装了底层细节,@RequestParam("file") MultipartFile file 就能直接拿到内容、原始名、大小,连流都不用自己关。硬套 Commons FileUpload 反而绕路,还容易和 Spring 的 multipart resolver 冲突(比如重复解析请求体)。
唯一需要 Commons 的场景:你要在非 Spring 环境(如裸 Servlet/JSP)里做上传,或者必须用 FileItem 的某些低阶 API(如进度监听)。否则,Spring 的 MultipartFile 更稳、更易测、自动清理临时文件。
- Spring Boot 2.0+ 默认启用 multipart,无需额外依赖(
spring-boot-starter-web已包含) - 上传失败时,Spring 会抛
MultipartException,比捕获FileUploadException更语义化 - 如果必须兼容旧 Commons 代码,至少把
ServletFileUpload实例做成单例,避免每次请求都 new 一个
真正麻烦的从来不是调哪个方法,而是边界情况:超时中断后临时文件残留、Nginx 转发时 client_max_body_size 比 Java 层限制更早拦截、iOS Safari 对 download 属性的支持缺失……这些地方没日志、不压测,上线就卡住。










