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

Java 文件上傳完整 Demo (Commons FileUpload + Servlet 3.0 對比)

     編輯:Java 相關知識

方案一:Commons FileUpload (通用、Servlet 2.5+)

依賴


commons-fileupload-1.3.3.jar
commons-io-2.6.jar

Servlet 實現


@WebServlet("/upload")
@MultipartConfig // Servlet 3.0+ 原生支持,見方案二
public class UploadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        // 1. 檢查 Content-Type
        if (!ServletFileUpload.isMultipartContent(req)) {
            resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "非 multipart 請求");
            return;
        }

        // 2. 配置工廠
        DiskFileItemFactory factory = new DiskFileItemFactory();
        factory.setRepository(new File(getServletContext().getRealPath("/tmp"))); // 臨時文件目錄
        factory.setSizeThreshold(1024 * 1024); // 1MB 以下內存,以上磁盤

        // 3. 解析請求
        ServletFileUpload upload = new ServletFileUpload(factory);
        upload.setFileSizeMax(10 * 1024 * 1024); // 單文件 10MB
        upload.setSizeMax(50 * 1024 * 1024);    // 總請求 50MB

        try {
            List items = upload.parseRequest(req);
            for (FileItem item : items) {
                if (item.isFormField()) {
                    // 普通表單字段
                    String fieldName = item.getFieldName();
                    String value = item.getString("UTF-8");
                    System.out.println("Field: " + fieldName + " = " + value);
                } else {
                    // 文件字段
                    String fileName = new File(item.getName()).getName(); // 防路徑遍歷
                    String ext = fileName.substring(fileName.lastIndexOf('.'));
                    String savedName = UUID.randomUUID().toString() + ext;
                    File saveDir = new File(getServletContext().getRealPath("/upload"));
                    if (!saveDir.exists()) saveDir.mkdirs();
                    File savedFile = new File(saveDir, savedName);
                    item.write(savedFile); // 寫入最終位置 (自動處理臨時文件清理)
                    System.out.println("Saved: " + savedName);
                }
            }
            resp.sendRedirect("ok.jsp");
        } catch (FileUploadException e) {
            throw new ServletException("解析失敗", e);
        } catch (Exception e) {
            throw new ServletException("保存失敗", e);
        }
    }
}

方案二:Servlet 3.0 原生 @MultipartConfig (無第三方依賴)


@WebServlet("/upload")
@MultipartConfig(
    location = "/tmp",                    // 臨時文件目錄
    fileSizeThreshold = 1024 * 1024,      // 1MB
    maxFileSize = 10 * 1024 * 1024,       // 10MB
    maxRequestSize = 50 * 1024 * 1024     // 50MB
)
public class UploadServlet3 extends HttpServlet {
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        for (Part part : req.getParts()) {
            if (part.getSize() == 0) continue; // 空字段
            String cd = part.getHeader("Content-Disposition");
            boolean isFile = cd != null && cd.contains("filename=");
            if (isFile) {
                String fileName = Paths.get(part.getSubmittedFileName()).getFileName().toString();
                String ext = fileName.substring(fileName.lastIndexOf('.'));
                String savedName = UUID.randomUUID() + ext;
                part.write(getServletContext().getRealPath("/upload") + File.separator + savedName);
            } else {
                String value = new String(part.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
                System.out.println(part.getName() + " = " + value);
            }
        }
        resp.sendRedirect("ok.jsp");
    }
}

前端表單 (通用)


用戶名:
頭像:

關鍵安全點

  1. 文件名清洗:new File(item.getName()).getName() 或 Paths.get(...).getFileName() 防止 ../../etc/passwd。
  2. 類型驗證:勿信任 Content-Type,需檢查 Magic Number (文件頭) 或擴展名白名單。
  3. 大小限制:工廠/解析器/註解雙重限制,防止 DoS。
  4. 存儲隔離:上傳目錄置於 Web 根目錄外,或配置 Nginx 禁止腳本執行。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved