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

Apache Commons FileUpload 組件實戰:常見坑與最佳實踐總結

     編輯:Java 相關知識

前言

在使用 commons-fileupload 處理檔案上傳時,踩過不少坑。本文整理依賴管理、權限配置、版本遷移與標準寫法,助你避開雷區。

一、依賴套件版本陷阱

舊教程常建議 commons-beanutils.jar,實測不需要。真正關鍵的是 commons-io,因為 DiskFileItem 內部依賴 DeferredFileOutputStream。

二、應用伺服器檔案系統權限

WebLogic 等容器預設安全策略限制檔案讀寫。需在 weblogic.policy 加入:

permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete";

否則會噴 FileUploadException: InvocationTargetException 錯誤堆疊。

三、標準 Servlet 寫法 (FileUpload 1.1+)

舊版 parseRequest(request) 回傳 List<FileItem>,新版建議搭配 ServletFileUpload 與 DiskFileItemFactory。

public class FileUploadServlet extends HttpServlet {
    private String uploadPath = "D:/addnetFile/";
    private File tempPath = new File("D:/addnetFile/tmp/");

    protected void doPost(HttpServletRequest req, HttpServletResponse res) 
            throws ServletException, IOException {
        res.setContentType("text/html; charset=GB2312");
        PrintWriter out = res.getWriter();

        DiskFileItemFactory factory = new DiskFileItemFactory();
        factory.setSizeThreshold(4096); // 4KB 以上存臨時檔
        factory.setRepository(new File("d:/File/addnetFile/temp"));

        ServletFileUpload upload = new ServletFileUpload(factory);
        upload.setSizeMax(1000000); // 限制 1MB

        try {
            List<FileItem> items = upload.parseRequest(req);
            Iterator<FileItem> iter = items.iterator();

            // 正則取檔名 (去除路徑)
            Pattern p = Pattern.compile(".+\\\\(.+)$");
            String[] errorTypes = {".exe", ".com", ".cgi", ".asp"};

            while (iter.hasNext()) {
                FileItem item = iter.next();
                if (item.isFormField()) continue; // 忽略一般表單欄位

                String name = item.getName();
                if (name == null || name.isEmpty() || item.getSize() == 0) continue;

                Matcher m = p.matcher(name);
                if (!m.find()) throw new IOException("檔名解析失敗");

                String fileName = m.group(1);
                // 檢查副檔名黑名單
                for (String ext : errorTypes) {
                    if (fileName.toLowerCase().endsWith(ext)) {
                        throw new IOException("禁止上傳執行檔:" + fileName);
                    }
                }

                // 儲存檔案
                File savedFile = new File(uploadPath + fileName);
                item.write(savedFile);
                out.print(fileName + " " + item.getSize() + "<br>");
            }
        } catch (FileUploadException | IOException e) {
            out.println("上傳失敗:" + e.getMessage());
        }
    }
}

四、前端表單關鍵點

<form action="FileUploadServlet" method="post" enctype="multipart/form-data">
  <input type="file" name="file1">
  <input type="file" name="file2">
  <input type="submit" value="上傳">
</form>
  • enctype="multipart/form-data" 必須設定
  • name 屬性對應後端 FileItem.getFieldName()

五、不同容器的行為差異

Tomcat、WebLogic、Resin 對臨時目錄、請求解析行為略有不同,建議:

  • 明確指定 factory.setRepository(...)
  • 測試時觀察 req.getContentType() 與 req.getContentLength()
  • 大檔案上傳調整 setSizeThreshold 與 setSizeMax

總結

  1. 引對依賴:fileupload + io,別信舊文檔加 beanutils。
  2. 給權限:Policy 檔加 FilePermission。
  3. 用新 API:ServletFileUpload + DiskFileItemFactory。
  4. 防惡意:副檔名白/黑名單、檔案大小限制、病毒掃描整合。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
套件版本說明
commons-fileupload1.1-dev核心上傳處理
commons-io1.1-dev必須,缺少會拋 ClassNotFoundException: DeferredFileOutputStream