首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring MVC 文件上傳完整實戰:CommonsMultipartResolver 配置與 MultipartFile 處理詳解

     編輯:Java 相關知識

依賴引入 (Maven)

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version> <!-- 建議升級至 1.4 修復安全漏洞 -->
</dependency>
<!-- Spring MVC 已傳遞依賴 commons-io -->

核心配置:MultipartResolver Bean

<!-- dispatcher-servlet.xml -->
<bean id="multipartResolver" 
      class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 最大上傳 10MB -->
    <property name="maxUploadSize" value="10485760" />
    <!-- 內存臨界值 100KB,超過寫入臨時文件 -->
    <property name="maxInMemorySize" value="102400" />
    <!-- 臨時文件存放路徑 -->
    <property name="uploadTempDir" value="/tmp/uploads" />
    <!-- 編碼設置 -->
    <property name="defaultEncoding" value="UTF-8" />
</bean>

關鍵屬性:

  • maxUploadSize:總請求大小限制(含表單字段),-1 為無限制
  • maxInMemorySize:內存緩衝閾值,超過寫磁盤臨時文件,防 OOM
  • resolveLazily:是否延遲解析(默認 false),true 可在 Controller 手動控制

前端表單:關鍵屬性 enctype

<form method="POST" action="/upload.do" enctype="multipart/form-data">
    <input type="file" name="file" />
    <input type="text" name="description" />
    <button type="submit">上傳</button>
</form>

enctype="multipart/form-data" 必須設置,否則請求體不會被解析為多部分,MultipartFile 為 null。

Controller 處理:MultipartFile API 詳解

@Controller
@RequestMapping("/file")
public class FileUploadController {
    
    private static final String UPLOAD_DIR = "WEB-INF/upload";
    private static final long MAX_SIZE = 10 * 1024 * 1024; // 10MB
    private static final Set ALLOWED_TYPES = Set.of(
        "image/jpeg", "image/png", "application/pdf", "text/plain"
    );
    
    @PostMapping("/upload.do")
    public String upload(@RequestParam("file") MultipartFile file,
                         @RequestParam(value = "desc", required = false) String desc,
                         RedirectAttributes redirectAttrs) {
        
        // 1. 基礎校驗
        if (file.isEmpty()) {
            redirectAttrs.addFlashAttribute("error", "請選擇文件");
            return "redirect:/upload.html";
        }
        if (file.getSize() > MAX_SIZE) {
            redirectAttrs.addFlashAttribute("error", "文件超過 10MB 限制");
            return "redirect:/upload.html";
        }
        if (!ALLOWED_TYPES.contains(file.getContentType())) {
            redirectAttrs.addFlashAttribute("error", "不支持的文件類型");
            return "redirect:/upload.html";
        }
        
        // 2. 生成安全文件名:UUID + 原始後綴
        String originalName = file.getOriginalFilename();
        String suffix = originalName.substring(originalName.lastIndexOf("."));
        String savedName = UUID.randomUUID() + suffix;
        
        // 3. 目標路徑:實際部署路徑 + 相對目錄
        String realPath = request.getServletContext().getRealPath(UPLOAD_DIR);
        File destDir = new File(realPath);
        if (!destDir.exists()) destDir.mkdirs();
        
        File destFile = new File(destDir, savedName);
        
        // 4. 保存文件:transferTo 內部優化(大文件直接 rename,小文件流拷貝)
        try {
            file.transferTo(destFile);
            log.info("文件上傳成功: {} -> {}", originalName, destFile.getAbsolutePath());
            redirectAttrs.addFlashAttribute("msg", "上傳成功: " + savedName);
        } catch (IOException e) {
            log.error("文件保存失敗", e);
            redirectAttrs.addFlashAttribute("error", "服務器內部錯誤");
        }
        
        return "redirect:/upload.html";
    }
}

MultipartFile 核心方法速查

方法說明
getOriginalFilename()客戶端原始文件名(可能含路徑,需 FilenameUtils.getName() 清洗)
getContentType()MIME 類型(瀏覽器根據後綴推測,不可完全信任)
getSize()文件字節大小
isEmpty()大小為 0
getInputStream()獲取輸入流(需手動關閉)
transferTo(File dest)推薦:高性能保存,自動處理內存/臨時文件
getBytes()全量讀入 byte[](大文件慎用,OOM 風險)

Spring Boot 簡化配置 (application.yml)

spring:
  servlet:
    multipart:
      enabled: true
      max-file-size: 10MB
      max-request-size: 100MB
      file-size-threshold: 100KB
      location: /tmp/uploads

無需手動定義 Bean,自動裝配 StandardServletMultipartResolver(基於 Servlet 3.0 Part API,無需 commons-fileupload)。

安全與生產環境加固

  1. 文件類型二次校驗:魔數檢測(如 JPEG `FF D8 FF`、PNG `89 50 4E 47`),防偽造 Content-Type
  2. 路徑遍歷防護:FilenameUtils.getName() 截取純文件名,禁止 `../`
  3. 存儲隔離:上傳目錄禁用腳本執行權限,獨立域名/CDN 分發
  4. 病毒掃描:集成 ClamAV 或雲端安全服務異步掃描
  5. 限流熔斷:接口級 QPS 限制,防惡意佔用帶寬
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved