jQuery Uploadify 是基於 Flash 的多文件上傳組件,雖然技術較老,但在維護舊系統時仍常遇到。本文演示 Spring MVC 4 環境下,從表單上傳遷移到 Uploadify 的完整過程,重點解決「Request Payload 導致 400 錯誤」的參數綁定問題。
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<!-- 自動引入 commons-io、commons-logging -->
src/main
├── java
│ └── com.example
│ ├── controller
│ │ └── UserController.java
│ └── config
│ └── WebMvcConfig.java
├── resources
└── webapp
├── uploadify
│ ├── uploadify.swf
│ ├── uploadify.css
│ └── jquery.uploadify.js
├── js
│ └── jquery-1.4.2.js
└── index.jsp

<form action="/User/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="upload"/>
</form>
@PostMapping("/upload")
@ResponseBody
public String upload(@RequestParam MultipartFile file) throws IOException {
String path = request.getServletContext().getRealPath("upload");
File dest = new File(path, file.getOriginalFilename());
file.transferTo(dest);
return "success";
}
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<title>Spring MVC Uploadify Demo</title>
<link href="/uploadify/uploadify.css" rel="stylesheet"/>
<script src="/js/jquery-1.4.2.js"></script>
<script src="/uploadify/jquery.uploadify.js"></script>
<style>#fileQueue {position:absolute; bottom:0; right:0;}</style>
</head>
<body>
<div id="fileQueue"></div>
<input type="file" name="uploadify" id="uploadify"/>
<script>
$(function() {
$("#uploadify").uploadify({
'method' : 'post',
'swf' : '/uploadify/uploadify.swf',
'uploader' : '/User/upload',
'buttonText' : '上傳圖片',
'fileTypeDesc': 'Image Files',
'fileTypeExts': '*.gif; *.jpg; *.png',
'formData' : { 'someKey': 'someValue' },
'queueID' : 'fileQueue',
'auto' : true,
'multi' : true
});
});
</script>
</body>
</html>
MultipartHttpServletRequestUploadify 發送的是 multipart/form-data 但參數以 Request Payload 形式傳遞,導致 @RequestParam MultipartFile 綁定失敗(HTTP 400)。解決方案:注入 MultipartHttpServletRequest 手動解析文件映射。
@PostMapping("/upload")
@ResponseBody
public String upload(HttpServletRequest request, HttpServletResponse response) {
String saveDir = request.getServletContext().getRealPath("upload");
File dir = new File(saveDir);
if (!dir.exists()) dir.mkdirs();
MultipartHttpServletRequest mpRequest = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> fileMap = mpRequest.getFileMap();
try {
for (Map.Entry<String, MultipartFile> entry : fileMap.entrySet()) {
MultipartFile mf = entry.getValue();
File dest = new File(saveDir, mf.getOriginalFilename());
mf.transferTo(dest);
}
return "success";
} catch (Exception e) {
e.printStackTrace();
return "error";
}
}

| 維度 | 表單上傳 | Uploadify 上傳 |
|---|---|---|
| Content-Type | multipart/form-data | multipart/form-data |
| 參數呈現 | Form Data (瀏覽器原生) | Request Payload (Flash 模擬) |
| Spring 綁定 | @RequestParam MultipartFile 直接支持 | 需 MultipartHttpServletRequest.getFileMap() |
| 多文件 | 多個 <input name="file"> | 自動隊列,單請求多部分 |
<input type="file" multiple> + FormData + AJAX,無需 Flashcommons-fileupload 版本兼容 Servlet 容器本示例展示了 Spring MVC 處理非標準 multipart 請求的通用技巧,同樣適用於其他 Flash/ActiveX 上傳組件遷移場景。