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

Apache Commons FileUpload 實戰:從基礎上傳到 Servlet 完整整合指南

     編輯:Java 相關知識

Apache Commons FileUpload 是 Java Web 文件上傳的經典解決方案。本文以版本 1.2 為基礎 (需搭配 Commons IO 1.3.2),透過四個漸進式範例,從最簡單的表單解析、多檔上傳、檔案大小限制,到 Servlet 整合部署,完整展示實務用法。

環境準備

  • 將 commons-fileupload-1.2.jar、commons-io-1.3.2.jar 放入 WEB-INF/lib
  • Eclipse 3.3 + MyEclipse 6.0 測試環境
  • 本文完整範例專案可下載 (文末附件)

核心類別速覽

  • ServletFileUpload:靜態工具類,解析 multipart/form-data 請求
  • FileItemFactory / DiskFileItemFactory:建立 FileItem 實例,控制記憶體/磁碟臨界值
  • FileItem:代表單一表單欄位 (一般欄位或檔案),提供 getName()、getString()、isFormField()、write(File) 等方法

範例 1:最簡單表單解析

demo1.html - 上傳表單 (必須設 enctype="multipart/form-data")

<form name="myform" action="demo1.jsp" method="post"
 enctype="multipart/form-data">
 Your name: <br>
 <input type="text" name="name" size="15"><br>
 File:<br>
 <input type="file" name="myfile"><br>
 <input type="submit" name="submit" value="Commit">
</form>

demo1.jsp - 解析並顯示欄位與檔名

<%@ page import="org.apache.commons.fileupload.*" %>
<%@ page import="org.apache.commons.fileupload.servlet.*" %>
<%@ page import="org.apache.commons.fileupload.disk.*" %>
<%@ page import="java.util.*" %>
<%
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (isMultipart) {
    FileItemFactory factory = new DiskFileItemFactory();
    ServletFileUpload upload = new ServletFileUpload(factory);
    List<FileItem> items = upload.parseRequest(request);
    Iterator<FileItem> itr = items.iterator();
    while (itr.hasNext()) {
        FileItem item = itr.next();
        if (item.isFormField()) {  // 一般表單欄位
            String fieldName = item.getFieldName();
            if ("name".equals(fieldName))
                out.print("the field name is" + item.getString());
            out.print("<br>");
        } else {  // 上傳檔案
            out.print("the upload file name is" + item.getName());
            out.print("<br>");
        }
    }
} else {
    out.print("the enctype must be multipart/form-data");
}
%>

執行結果

the field name isjeff
the upload file name isD:\C語言考試樣題\作業題.rar

範例 2:多檔上傳至指定目錄

demo2.html - 兩個 file 欄位 (同名 myfile)

<input type="file" name="myfile"><br>
<input type="file" name="myfile"><br>

demo2.jsp - 迭代儲存

<% String uploadPath = "D:\\temp"; %>
<%
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (isMultipart) {
    try {
        FileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload upload = new ServletFileUpload(factory);
        List<FileItem> items = upload.parseRequest(request);
        Iterator<FileItem> itr = items.iterator();
        while (itr.hasNext()) {
            FileItem item = itr.next();
            String fileName = item.getName();
            if (fileName != null) {
                File fullFile = new File(item.getName());
                File savedFile = new File(uploadPath, fullFile.getName());
                item.write(savedFile);  // 核心儲存方法
            }
        }
        out.print("upload succeed");
    } catch (Exception e) { e.printStackTrace(); }
} else {
    out.println("the enctype must be multipart/form-data");
}
%>

結果:D:\temp 下出現兩個上傳檔案。

範例 3:單檔上傳 + 大小限制 + 緩衝區配置

demo3.jsp - 關鍵配置

File uploadPath = new File("D:\\temp");
if (!uploadPath.exists()) uploadPath.mkdirs();

// 臨時緩衝區目錄 (超過 sizeThreshold 寫入磁碟)
File tempPathFile = new File("d:\\temp\\buffer\\");
if (!tempPathFile.exists()) tempPathFile.mkdirs();

DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(4096);        // 4KB 記憶體緩衝區
factory.setRepository(tempPathFile);   // 緩衝區目錄

ServletFileUpload upload = new ServletFileUpload(factory);
upload.setSizeMax(4194304);            // 4MB 最大檔案限制

// 後續 parseRequest、iterate、write 同範例 2

關鍵參數說明:

  • setSizeThreshold:超過此大小 (bytes) 改用磁碟暫存,防止大檔吃光記憶體
  • setRepository:磁碟暫存目錄
  • setSizeMax:整體請求大小上限,超過拋出 SizeLimitExceededException

範例 4:Servlet 方式整合 (生產環境推薦)

Upload.java - 完整 Servlet 實作

package com.zj.sample;

import java.io.File;
import java.io.IOException;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.commons.fileupload.*;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class Upload extends HttpServlet {
    private String uploadPath = "D:\\temp";
    private String tempPath = "d:\\temp\\buffer\\";
    File tempPathFile;

    public void init() throws ServletException {
        new File(uploadPath).mkdirs();
        tempPathFile = new File(tempPath);
        tempPathFile.mkdirs();
    }

    @SuppressWarnings("unchecked")
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
        try {
            DiskFileItemFactory factory = new DiskFileItemFactory();
            factory.setSizeThreshold(4096);
            factory.setRepository(tempPathFile);

            ServletFileUpload upload = new ServletFileUpload(factory);
            upload.setSizeMax(4194304);  // 4MB

            List<FileItem> items = upload.parseRequest(request);
            Iterator<FileItem> i = items.iterator();
            while (i.hasNext()) {
                FileItem fi = i.next();
                String fileName = fi.getName();
                if (fileName != null) {
                    File fullFile = new File(fi.getName());
                    File savedFile = new File(uploadPath, fullFile.getName());
                    fi.write(savedFile);
                }
            }
            System.out.print("upload succeed");
        } catch (Exception e) {
            e.printStackTrace();  // 實務應導向錯誤頁面
        }
    }
}

demo4.html - 表單指向 Servlet 映射路徑

<form name="myform" action="fileupload" method="post"
 enctype="multipart/form-data">
 File:<br>
 <input type="file" name="myfile"><br>
 <input type="submit" name="submit" value="Commit">
</form>

web.xml - Servlet 映射配置

<servlet>
  <servlet-name>Upload</servlet-name>
  <servlet-class>com.zj.sample.Upload</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>Upload</servlet-name>
  <url-pattern>/fileupload</url-pattern>
</servlet-mapping>

實務注意事項

  1. 檔名處理: item.getName() 可能包含客戶端完整路徑 (IE 行為),建議用 new File(fileName).getName() 取純檔名
  2. 編碼問題: 檔名中文亂碼需配合 ServletFileUpload.setHeaderEncoding("UTF-8") 或手動轉碼
  3. 安全性: 嚴格驗證副檔名、MIME 類型、檔案內容,防止惡意腳本上傳
  4. 資源清理: 異常情況下臨時檔案需手動清理,或配置定時清理任務
  5. 大檔上傳: 生產環境建議採用分片上傳、斷點續傳方案 (如 Plupload、Resumable.js)

本文出自「子孑」部落格,轉載請保留出處:https://zhangjunhd.blog.51cto.com/113473/18331

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