使用 SpringMVC + Red5 服務器進行文件上傳,Controller 中 commonsMultipartResolver.isMultipart(request) 返回 false,無法獲取上傳文件,但 request.getParameter("upload") 能獲取到文件名。手動轉型 MultipartHttpServletRequest 拋出 ClassCastException。
MultipartResolver Bean,且 id 必須為 multipartResolver。HttpServletRequest 仍為原始請求,非 MultipartHttpServletRequest。enctype="multipart/form-data"。<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"/>
<property name="maxUploadSize" value="209715200"/> <!-- 200MB -->
<property name="maxInMemorySize" value="1048576"/> <!-- 1MB -->
</bean>
關鍵點:Bean id 必須為 multipartResolver,Spring 會自動檢測此 Bean。
無需手動創建 Resolver,直接使用 @RequestParam("file") MultipartFile file:
@PostMapping("/upload.do")
public String upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
if (file.isEmpty()) {
return "error";
}
try {
String path = "/WEB-INF/upload/" + file.getOriginalFilename();
File dest = new File(request.getServletContext().getRealPath(path));
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
file.transferTo(dest);
return "success";
} catch (IOException e) {
e.printStackTrace();
return "error";
}
}
<form action="/upload.do" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" value="上傳" />
</form>
| 問題 | 原因 | 解決 |
|---|---|---|
| isMultipart 返回 false | Resolver 未生效或 id 錯誤 | 檢查 Bean id=multipartResolver 且掃描到配置類 |
| ClassCastException | 請求未被包裝為 MultipartHttpServletRequest | 同上,Resolver 未工作 |
| 大文件上傳失敗/慢 | 默認內存閾值小,頻繁寫臨時文件 | 調大 maxInMemorySize,或改用流式上傳 |
| 文件名亂碼 | 編碼不一致 | 設置 defaultEncoding=utf-8,Tomcat 8+ 通常無問題 |
若文件較大(>100MB),建議:
StandardServletMultipartResolver (Servlet 3.0+) 替代 Commons,支援非阻塞 IO。client_max_body_size 和超時時間。Red5 基於 Jetty/Tomcat,確保 commons-fileupload 和 commons-io 依賴版本與容器兼容。若在 Red5 插件中開發,注意類加載器隔離問題,確保 Spring 容器能掃描到配置。
核心原則:**讓 Spring 容器管理 MultipartResolver,Controller 僅接收 MultipartFile 參數**,避免手動解析請求導致的類型轉換與生命周期問題。