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

Apache Commons FileUpload 文件上傳完整指南:Servlet 實現與配置詳解

     編輯:Java 相關知識

Web 開發中文件上傳是高頻需求。Servlet 3.0+ 雖原生支持 @MultipartConfig,但 Apache Commons FileUpload 仍是兼容性最好、功能最豐富的選擇。本文從依賴引入、前端表單、Servlet 核心代碼、配置參數、進階功能(大小限制、編碼、臨時目錄、進度監聽)全方位講解。

一、依賴引入

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
</dependency>

二、前端表單關鍵點

<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="text" name="username" placeholder="用戶名" />
    <input type="file" name="file1" />
    <input type="file" name="file2" multiple />
    <button type="submit">上傳</button>
</form>
  • enctype="multipart/form-data":必須設置,否則請求體不會被解析為多部分
  • method="post":GET 無法攜帶文件數據
  • multiple 屬性允許單個 file 控件選擇多文件

三、Servlet 核心實現

@WebServlet("/upload")
@MultipartConfig  // Servlet 3.0+ 可選,FileUpload 不依賴此註解
public class UploadServlet extends HttpServlet {
    
    private static final long MAX_FILE_SIZE = 10 * 1024 * 1024;   // 10 MB
    private static final long MAX_REQUEST_SIZE = 50 * 1024 * 1024; // 50 MB
    private static final String UPLOAD_DIR = "upload";
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        
        resp.setContentType("text/plain;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        
        // 1. 創建工廠:設置內存閾值與臨時目錄
        DiskFileItemFactory factory = new DiskFileItemFactory();
        factory.setSizeThreshold(4 * 1024); // 4 KB 以上寫入臨時文件
        factory.setRepository(new File(getServletContext().getRealPath("/tmp")));
        
        // 2. 創建解析器
        ServletFileUpload upload = new ServletFileUpload(factory);
        upload.setFileSizeMax(MAX_FILE_SIZE);
        upload.setSizeMax(MAX_REQUEST_SIZE);
        upload.setHeaderEncoding("UTF-8"); // 解決中文文件名亂碼
        
        // 3. 解析請求
        try {
            List items = upload.parseRequest(req);
            for (FileItem item : items) {
                if (item.isFormField()) {
                    // 普通表單字段
                    out.println(item.getFieldName() + " = " + item.getString("UTF-8"));
                } else {
                    // 文件字段
                    String fileName = Paths.get(item.getName()).getFileName().toString(); // 防止路徑遍歷
                    if (fileName.isEmpty()) continue;
                    
                    // 生成唯一文件名:UUID + 原文件名
                    String savedName = UUID.randomUUID() + "#" + fileName;
                    File saveDir = new File(getServletContext().getRealPath(UPLOAD_DIR));
                    if (!saveDir.exists()) saveDir.mkdirs();
                    
                    File savedFile = new File(saveDir, savedName);
                    item.write(savedFile); // 寫入最終位置
                    item.delete(); // 刪除臨時文件
                    
                    out.println("文件上傳成功: " + fileName + " → " + savedName);
                    out.println("大小: " + item.getSize() + " bytes");
                }
            }
        } catch (FileUploadException e) {
            out.println("解析失敗: " + e.getMessage());
        } catch (Exception e) {
            out.println("處理異常: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

四、web.xml 配置(非 Servlet 3.0 環境)

<servlet>
    <servlet-name>upload</servlet-name>
    <servlet-class>com.example.UploadServlet</servlet-class>
    <init-param>
        <param-name>filePath</param-name>
        <param-value>upload</param-value>
    </init-param>
    <init-param>
        <param-name>tempFilePath</param-name>
        <param-value>tmp</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>upload</servlet-name>
    <url-pattern>/upload</url-pattern>
</servlet-mapping>

五、進階功能與最佳實踐

  1. 文件類型驗證:檢查 item.getContentType()、擴展名、魔數(文件頭字節)
  2. 大小限制:setFileSizeMax(單文件)、setSizeMax(總請求),超限拋 FileSizeLimitExceededException/SizeLimitExceededException
  3. 進度監聽:實現 ProgressListener 接口,前端 Ajax 輪詢進度
  4. 流式處理大文件:item.getInputStream() 直接流式寫入,避免 item.write() 內存拷貝
  5. 安全防範:
    • 文件名去路徑:Paths.get(name).getFileName()
    • 存儲目錄隔離 Web 根目錄
    • 執行權限移除:savedFile.setExecutable(false)
    • 病毒掃描集成(ClamAV 等)
  6. Spring MVC 整合:配置 CommonsMultipartResolver,Controller 直接用 MultipartFile 參數

六、常見問題排查

現象原因解決
item.isFormField() 全為 true表單缺少 enctype添加 enctype="multipart/form-data"
中文文件名亂碼編碼不一致upload.setHeaderEncoding("UTF-8")
上傳大文件失敗超過默認限制調大 setSizeMax、setFileSizeMax
臨時文件未清理異常路徑未 deletefinally 塊調用 item.delete()

七、總結

Commons FileUpload 以成熟穩定、配置靈活、兼容性強成為文件上傳首選。掌握 DiskFileItemFactory、ServletFileUpload 核心類,配合大小限制、編碼處理、安全防範、流式寫入最佳實踐,能構建企業級可靠上傳服務。Servlet 3.0+ 環境下可考慮原生 API 簡化依賴,但 FileUpload 仍是遷移期與老項目維護的最佳選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved