瀏覽器上傳文件時,表單需設置 enctype="multipart/form-data",請求體將包含多個部分,每部分對應一個表單字段或文件。Spring MVC 通過 MultipartResolver 介面統一解析,核心實現 CommonsMultipartResolver 依賴 Apache Commons FileUpload。
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<!-- 間接依賴 commons-io:2.2 -->
在 Spring MVC 配置文件(如 springmvc.xml)中聲明 Bean:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="5242880" /> <!-- 5MB -->
<property name="maxInMemorySize" value="1048576" /> <!-- 1MB 閾值,超過寫臨時文件 -->
<property name="defaultEncoding" value="UTF-8" />
</bean>
關鍵屬性:maxUploadSize 限制總大小;maxInMemorySize 控制內存緩衝閾值,防止大文件撐爆堆內存。
上傳文件不應放在 Webapp 目錄下(重新部署會丟失、靜態資源服務壓力大)。推薦方案:
/data/upload/images)映射為 /images/**。server.xml 中 <Context docBase="/data/upload/images" path="/images" />。/images/2024/05/20/uuid.jpg,避免單目錄文件過多導致 I/O 性能下降。<form action="${pageContext.request.contextPath}/items/editItemsSubmit" method="post" enctype="multipart/form-data">
<c:if test="${items.pic != null}">
<img src="/images/${items.pic}" width="100" height="100" />
</c:if>
<input type="file" name="items_pic" />
<input type="submit" value="提交" />
</form>
@RequestMapping("/editItemsSubmit")
public String editItemsSubmit(
Model model, HttpServletRequest request,
Integer id,
@ModelAttribute("items") @Validated(ValidGroup1.class) ItemsCustom itemsCustom,
BindingResult bindingResult,
MultipartFile items_pic) throws Exception {
// 1. 校驗文件
String originalFilename = items_pic.getOriginalFilename();
if (items_pic != null && originalFilename != null && originalFilename.length() > 0) {
// 2. 生成唯一文件名:UUID + 原始後綴
String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
String newFileName = UUID.randomUUID().toString() + suffix;
// 3. 寫入磁盤(生產環境應注入存儲服務抽象層)
String picPath = "D:/tmp/"; // 應從配置讀取
File newFile = new File(picPath + newFileName);
items_pic.transferTo(newFile); // Commons FileUpload 核心方法
// 4. 保存文件名至領域對象
itemsCustom.setPic(newFileName);
}
// 5. 業務邏輯:更新數據庫...
itemsService.updateItems(itemsCustom);
return "success";
}
StandardServletMultipartResolver(Servlet 3.0+ 原生支持)或分片上傳插件。Content-Type、魔數檢測防止偽裝腳本上傳。transferTo 替換為 OSS SDK 上傳,Controller 無感遷移。