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

Java FileUpload 組件文件上傳 Demo 完整範例

     編輯:Java 相關知識

專案概述

本文提供基於 Apache Commons FileUpload 組件的文件上傳完整 Demo,包含前端 JSP、後端 Servlet、結果頁面與 web.xml 配置,可直接部署至 Tomcat 等 Servlet 容器運行。

常用上傳組件對比

組件特點適用場景
Apache Commons FileUpload標準、輕量、社群活躍通用 Servlet/JSP 專案、Spring MVC 底層實作
JavaZoom UploadBean功能豐富、商業授權企業級需進階功能 (壓縮、水印、轉檔)
jspSmartUpload早期經典、已停止維護舊系統維護、不建議新專案採用

完整專案結構

WebApp/
├── WebContent/
│   ├── upload.jsp           # 上傳表單頁面
│   ├── uploadResult.jsp     # 上傳結果頁面
│   └── WEB-INF/
│       ├── web.xml          # 部署描述檔
│       └── lib/
│           ├── commons-fileupload-1.2.2.jar
│           └── commons-io-1.4.jar
└── src/
    └── com/b510/example/
        └── FileUploadServlet.java

核心代碼實作

1. 前端上傳表單 (upload.jsp)

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <title>Commons FileUpload 文件上傳</title>
    <meta charset="UTF-8">
    <style>
        body { font-family: "微軟正黑體", sans-serif; font-size: 14px; }
        .container { max-width: 600px; margin: 50px auto; padding: 20px; border: 1px solid #ddd; }
        .form-group { margin-bottom: 15px; }
        label { display: inline-block; width: 80px; text-align: right; margin-right: 10px; }
        input[type="file"] { border: 1px solid #ccc; padding: 5px; }
        .btn { padding: 8px 20px; margin-right: 10px; cursor: pointer; }
    </style>
</head>
<body>
    <div class="container">
        <h2 align="center">文件上傳測試</h2>
        <form id="uploadForm" action="servlet/fileServlet" method="post" enctype="multipart/form-data">
            <div class="form-group">
                <label>上傳人:</label>
                <input type="text" name="uploader" id="uploader" size="30" required/>
            </div>
            <div class="form-group">
                <label>選擇檔案:</label>
                <input type="file" name="uploadFile" id="uploadFile" required/>
            </div>
            <div class="form-group">
                <label></label>
                <input type="submit" class="btn" value="提交上傳">
                <input type="reset" class="btn" value="重置">
            </div>
        </form>
    </div>
</body>
</html>

2. 核心上傳 Servlet (FileUploadServlet.java)

package com.b510.example;

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.*;

public class FileUploadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private ServletContext servletContext;
    private String savePath; // 從 web.xml 讀取

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        this.servletContext = config.getServletContext();
        this.savePath = config.getInitParameter("savePath"); // 如 "uploads"
        
        // 初始化時建立目錄
        File uploadDir = new File(servletContext.getRealPath("/") + savePath);
        if (!uploadDir.exists()) uploadDir.mkdirs();
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        
        DiskFileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload upload = new ServletFileUpload(factory);
        upload.setHeaderEncoding("UTF-8"); // 解決中文檔名

        try {
            List<FileItem> items = upload.parseRequest(request);
            Iterator<FileItem> iter = items.iterator();
            
            String uploadMessage = "上傳失敗!";
            
            while (iter.hasNext()) {
                FileItem item = iter.next();
                
                if (item.isFormField()) {
                    // 處理一般表單欄位
                    String fieldName = item.getFieldName();
                    String fieldValue = item.getString("UTF-8");
                    System.out.println("表單參數: " + fieldName + " = " + fieldValue);
                } else {
                    // 處理上傳文件
                    String fileName = item.getName();
                    if (fileName != null && !fileName.isEmpty()) {
                        System.out.println("上傳檔案大小: " + item.getSize() + " bytes");
                        System.out.println("檔案類型: " + item.getContentType());
                        System.out.println("原始檔名: " + fileName);
                        
                        // 取得純檔名 (去除客戶端路徑)
                        File tempFile = new File(fileName);
                        String onlyFileName = tempFile.getName();
                        
                        // 為避免同名覆蓋,可加入 UUID 前綴
                        String savedName = UUID.randomUUID().toString() + "_" + onlyFileName;
                        
                        File savedFile = new File(servletContext.getRealPath("/") + savePath, savedName);
                        item.write(savedFile); // 自動清理暫存檔
                        
                        uploadMessage = "上傳成功!檔案已儲存為: " + savedName;
                    } else {
                        uploadMessage = "未選擇上傳檔案!";
                    }
                }
            }
            
            request.setAttribute("uploadMessage", uploadMessage);
            request.getRequestDispatcher("/uploadResult.jsp").forward(request, response);
            
        } catch (FileUploadException e) {
            e.printStackTrace();
            request.setAttribute("uploadMessage", "解析上傳請求失敗: " + e.getMessage());
            request.getRequestDispatcher("/uploadResult.jsp").forward(request, response);
        } catch (Exception e) {
            e.printStackTrace();
            request.setAttribute("uploadMessage", "系統錯誤: " + e.getMessage());
            request.getRequestDispatcher("/uploadResult.jsp").forward(request, response);
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}

3. 結果顯示頁面 (uploadResult.jsp)

<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <title>上傳結果</title>
    <meta charset="UTF-8">
    <style>
        .result-box { padding: 20px; border: 1px solid #4CAF50; background: #f1f8f4; margin: 20px auto; max-width: 600px; }
        .back-link { display: inline-block; margin-top: 15px; color: #2196F3; text-decoration: none; }
    </style>
</head>
<body>
    <div class="result-box">
        <h3>上傳處理結果</h3>
        <p><strong>${requestScope.uploadMessage}</strong></p>
        <a href="upload.jsp" class="back-link">← 返回繼續上傳</a>
    </div>
</body>
</html>

4. 部署描述檔 (web.xml)

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="https://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://xmlns.jcp.org/xml/ns/javaee 
    https://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">

    <servlet>
        <servlet-name>FileUploadServlet</servlet-name>
        <servlet-class>com.b510.example.FileUploadServlet</servlet-class>
        <init-param>
            <param-name>savePath</param-name>
            <param-value>uploads</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>FileUploadServlet</servlet-name>
        <url-pattern>/servlet/fileServlet</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>upload.jsp</welcome-file>
    </welcome-file-list>
</web-app>

Maven 依賴配置 (現代專案建議)

<dependencies>
    <!-- Servlet API (provided 由容器提供) -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
    
    <!-- Commons FileUpload -->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.4</version>
    </dependency>
    
    <!-- Commons IO (FileUpload 依賴) -->
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.11.0</version>
    </dependency>
</dependencies>

進階功能擴充建議

  1. 多檔案上傳:前端 <input type="file" name="files" multiple>,後端遍歷同名 FileItem
  2. 拖曳上傳:結合 HTML5 Drag & Drop API + AJAX (FormData) 實現無刷新上傳
  3. 進度條顯示:需配合 Servlet 3.0 @MultipartConfig + HttpServletRequest.getPart() 或 Spring MVC MultipartFile
  4. 斷點續傳:採用 Plupload、WebUploader 等前端組件 + 後端分片合併邏輯
  5. 圖片預覽/壓縮:整合 Thumbnailator、ImageIO 實現伺服端縮圖生成

常見問題排查

現象可能原因解決方案
item.isFormField() 全為 true表單缺少 enctype="multipart/form-data"檢查 form 標籤屬性
中文檔名亂碼未設定 Header 編碼upload.setHeaderEncoding("UTF-8")
大檔上傳失敗超過預設大小限制調整 upload.setSizeMax() 或容器配置
暫存檔殘留未呼叫 item.write() 或 item.delete()務必使用 item.write(File) 自動清理
權限拒絕目錄寫入權限不足確保 Servlet 容器進程有目錄寫入權限

總結

本 Demo 展示了 Commons FileUpload 的標準用法,涵蓋從表單提交、Servlet 解析、檔案儲存到結果回饋的完整流程。實際專案中建議封裝為通用工具類或整合 Spring MVC 的 MultipartResolver,並加入檔案類型驗證、大小限制、防毒掃描等安全機制。

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