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

Java 文件上傳實戰:Commons FileUpload 核心 API、配置與完整 Servlet 示例

     編輯:Java 綜合教學

文件上傳是 Web 開發高頻需求。Apache Commons FileUpload 是經典、穩定的解析庫,支援大文件流式處理、進度條、多文件、表單字段混合。本文給出 Maven 依賴、web.xml、JSP 表單、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>

web.xml 配置(Servlet 3.0+ 可用註解替代)

<servlet>
  <servlet-name>UploadServlet</servlet-name>
  <servlet-class>com.servlet.UploadServlet</servlet-class>
  <init-param>
    <param-name>filePath</param-name>
    <param-value>/data/upload/</param-value> <!-- 存儲目錄 -->
  </init-param>
  <multipart-config> <!-- Servlet 3.0 原生支援,可替代 FileUpload -->
    <max-file-size>52428800</max-file-size> <!-- 50MB -->
    <max-request-size>104857600</max-request-size>
    <file-size-threshold>1048576</file-size-threshold> <!-- 1MB 閾值寫磁盤 -->
  </multipart-config>
</servlet>
<servlet-mapping>
  <servlet-name>UploadServlet</servlet-name>
  <url-pattern>/servlet/UploadServlet</url-pattern>
</servlet-mapping>

前端表單(關鍵:enctype=multipart/form-data)

<form action="servlet/UploadServlet" method="post" enctype="multipart/form-data">
  <input type="file" name="file1"/><br/>
  <input type="file" name="file2"/><br/>
  <input type="text" name="description1" placeholder="文件1說明"/><br/>
  <input type="text" name="description2" placeholder="文件2說明"/><br/>
  <input type="submit" value="上傳"/>
</form>

核心 Servlet 代碼(流式寫入、大文件安全)

package com.servlet;
import org.apache.commons.fileupload.*;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.List;
@WebServlet("/servlet/UploadServlet")
public class UploadServlet extends HttpServlet {
    private String uploadPath;
    @Override public void init() {
        uploadPath = getServletConfig().getInitParameter("filePath");
        new File(uploadPath).mkdirs();
    }
    @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        // 1. 檢查是否 multipart
        if (!ServletFileUpload.isMultipartContent(req)) {
            out.println("請求不是 multipart/form-data"); return;
        }
        // 2. 工廠:設置內存閾值、臨時目錄
        DiskFileItemFactory factory = new DiskFileItemFactory();
        factory.setSizeThreshold(1024 * 1024); // 1MB 以上寫臨時文件
        factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
        // 3. 解析器:設置大小限制
        ServletFileUpload upload = new ServletFileUpload(factory);
        upload.setFileSizeMax(50 * 1024 * 1024); // 50MB
        upload.setSizeMax(100 * 1024 * 1024);  // 總請求 100MB
        try {
            List items = upload.parseRequest(req);
            for (FileItem item : items) {
                if (item.isFormField()) { // 普通表單字段
                    String val = item.getString("UTF-8");
                    out.printf("字段: %s = %s<br/>", item.getFieldName(), val);
                } else { // 文件字段
                    String fileName = new File(item.getName()).getName(); // 防路徑遍歷
                    File saveFile = new File(uploadPath, fileName);
                    try (InputStream in = item.getInputStream();
                         OutputStream outStream = new FileOutputStream(saveFile)) {
                        byte[] buf = new byte[8192];
                        int len;
                        while ((len = in.read(buf)) > 0) outStream.write(buf, 0, len);
                    }
                    out.printf("文件上傳成功: %s (%d bytes)<br/>", fileName, item.getSize());
                }
            }
        } catch (FileUploadException e) {
            out.println("解析失敗: " + e.getMessage());
        } catch (Exception e) {
            out.println("服務器錯誤: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

關鍵點總結

  1. 流式處理:DiskFileItemFactory 設閾值,大文件自動落盤,不佔堆內存。
  2. 安全性:new File(item.getName()).getName() 防止 `../../etc/passwd` 路徑遍歷;限制文件類型、大小、總請求大小。
  3. 編碼:item.getString("UTF-8") 統一 UTF-8,避免中文亂碼。
  4. 異常處理:捕獲 FileUploadException、SizeLimitExceededException 返回友好提示。
  5. Servlet 3.0+ 原生 API:req.getPart("file") 可完全替代 FileUpload,零依賴,推薦新項目使用。

生產級擴展

  • 異步上傳:前端分片 + 後端合併(WebUploader/Plupload + 臨時目錄 + 合併任務)。
  • 雲存儲直傳:簽名直傳 OSS/S3,後端僅存元數據。
  • 病毒掃描:集成 ClamAV 掃描上傳文件。
  • 圖片處理:上傳後異步觸發縮略圖、水印(參考 Thumbnailator 文章)。

上傳頁面

上傳成功

掌握 FileUpload 核心流程,輕松應對從簡單表單到大文件斷點續傳的各類上傳場景。

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