Spring MVC 以 MultipartFile 封裝上傳文件,配合 CommonsMultipartResolver 即可輕鬆實現單/多文件上傳。本文從配置、表單、Controller、服務層封裝四個層面,提供可直接落地的完整範例。
<!-- spring-mvc.xml -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"/>
<property name="maxUploadSize" value="5242880"/> <!-- 5MB -->
<property name="maxInMemorySize" value="1048576"/> <!-- 1MB 超過寫臨時檔 -->
</bean>
defaultEncoding:表單編碼,預防中文檔名亂碼maxUploadSize:總請求大小上限 (bytes)maxInMemorySize:記憶體緩衝閾值,超過自動寫入臨時目錄<form action="fileUpload.html" method="post" enctype="multipart/form-data"> <input type="file" name="file"/> <!-- 單檔 --> <input type="submit" value="上傳"/> </form> <form action="filesUpload.html" method="post" enctype="multipart/form-data"> <input type="file" name="files"/> <input type="file" name="files"/> <input type="file" name="files"/> <!-- 多檔:同 name --> <input type="submit" value="批次上傳"/> </form>
必須 加上enctype="multipart/form-data",否則請求體不會被解析為多部分,MultipartFile會是 null。
@Controller
@RequestMapping("/file")
public class FileUploadController {
@Autowired HttpServletRequest request;
/** 單檔上傳 */
@PostMapping("/upload")
public String upload(@RequestParam("file") MultipartFile file) {
saveFile(file);
return "redirect:/file/list.html";
}
/** 多檔上傳:同 name 綁定陣列 */
@PostMapping("/uploads")
public String uploads(@RequestParam("files") MultipartFile[] files) {
if (files != null) {
for (MultipartFile f : files) saveFile(f);
}
return "redirect:/file/list.html";
}
/** 共用儲存邏輯 */
private boolean saveFile(MultipartFile file) {
if (file == null || file.isEmpty()) return false;
try {
String realPath = request.getServletContext().getRealPath("/") + "upload/";
File dir = new File(realPath);
if (!dir.exists()) dir.mkdirs();
// 防止檔名衝突:可加 UUID 前綴
String filename = file.getOriginalFilename();
file.transferTo(new File(realPath + filename));
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
/** 列出已上傳檔案 */
@GetMapping("/list")
public ModelAndView list() {
String realPath = request.getServletContext().getRealPath("/") + "upload/";
File dir = new File(realPath);
String[] names = dir.list();
ModelAndView mav = new ModelAndView("list");
mav.addObject("files", names == null ? new String[0] : names);
return mav;
}
}
| 方法 | 說明 |
|---|---|
getOriginalFilename() | 客戶端原始檔名 (含路徑風險,建議只取檔名) |
getContentType() | MIME 類型 |
getSize() | 檔案大小 (bytes) |
getInputStream() | 讀取檔案流 |
transferTo(File dest) | 高效寫入目的地 (底層用 FileChannel) |
isEmpty() | 是否為空檔 |
UUID + 原始副檔名 或 雪花算法 ID 重命名。getOriginalFilename() 可能包含 ../,務必用 FilenameUtils.getName() 只取檔名。maxInMemorySize 或直接配置臨時目錄 uploadTempDir。application.yml 配置 spring.servlet.multipart,無需手動定義 Resolver Bean。MockMultipartFile 模擬上傳,無需真實 Servlet 容器。Spring MVC 文件上傳核心在於 CommonsMultipartResolver + enctype="multipart/form-data" + MultipartFile 參數綁定。掌握單檔/多檔綁定差異、封裝共用儲存邏輯、注意檔名安全與大檔配置,即可構建健壯的上傳功能。