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

Struts 2 文件上傳完整實戰:配置、限制、路徑解決與最佳實踐

     編輯:Java 相關知識

Struts 2 文件上傳從入門到精通:核心配置、大小類型限制、路徑獲取難點突破

文件上傳是 Web 應用的基礎功能,Struts 2 通過 fileUpload 攔截器提供強大支援。本文系統講解從前端表單到後端 Action 的完整鏈路,重點攻克路徑獲取失效、大文件限制突破、類型驗證等實戰難點。

前端表單關鍵點

<form action="UploadFile" method="post" enctype="multipart/form-data">
    <input type="file" name="source" />
    <input type="submit" value="上傳">
</form>

三個必要條件:

  1. method="post":GET 請求不支援文件傳輸
  2. enctype="multipart/form-data":編碼類型必須正確
  3. name="source":與 Action 屬性名稱對應

Struts.xml 核心配置詳解

<action name="UploadFile" class="com.example.action.UploadAction">
    <result name="success">/uploadResult.jsp</result>
    
    <!-- fileUpload 攔截器:限制大小、類型 -->
    <interceptor-ref name="fileUpload">
        <param name="maximumSize">20971520</param> <!-- 20MB,單位字節 -->
        <param name="allowedTypes">image/jpeg,image/png,image/gif</param>
    </interceptor-ref>
    
    <!-- 必須聲明在 fileUpload 之後 -->
    <interceptor-ref name="defaultStack" />
</action>

全局最大上傳限制(突破 2MB 默認值)

在 <struts> 根節點下添加:

<constant name="struts.multipart.maxSize" value="21000000" /> <!-- 約 20MB -->

原理:此常量控制整個應用所有上傳點的單文件最大值,Action 級別的 maximumSize 不能超過此全局值。

文件類型限制:MIME 類型配置

限制類型allowedTypes 值來源
圖片image/bmp,image/png,image/gif,image/jpeg%TOMCAT_HOME%/conf/web.xml
Word 文檔application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.documentIANA MIME 標準
PDFapplication/pdf標準 MIME

建議:前端 JS 先做擴展名/MIME 初步攔截,後端再做嚴格驗證,雙重保障。

Action 類屬性映射規則(核心)

假設表單 <input type="file" name="abc" />,Action 必須聲明:

private File abc;                    // 文件對象
private String abcFileName;          // 原始文件名
private String abcContentType;       // MIME 類型

命名規則:{name}、{name}FileName、{name}ContentType,Struts 2 自動注入。

難點攻克:獲取項目根目錄下 upload 資料夾絕對路徑

常見失效代碼:

// 經常返回 null
ServletActionContext.getServletContext().getRealPath("/upload");
ServletActionContext.getRequest().getRealPath("/upload");

最佳解決方案:實現 ServletContextAware 接口

public class UploadAction extends ActionSupport implements ServletContextAware {
    private ServletContext context;
    
    @Override
    public void setServletContext(ServletContext context) {
        this.context = context; // Struts 2 自動注入
    }
    
    public String execute() throws IOException {
        // 關鍵:斜槓不能少!
        String path = context.getRealPath("/upload"); 
        
        File saveDir = new File(path);
        if (!saveDir.exists()) saveDir.mkdirs();
        
        File saveFile = new File(saveDir, sourceFileName);
        FileUtils.copyFile(source, saveFile); // 需 commons-io 依賴
        
        return SUCCESS;
    }
    // getter/setter 省略...
}

為什麼這樣做有效?

  • 容器啟動時將 ServletContext 注入 Action
  • getRealPath("/upload") 基於 Web 應用根目錄解析,打包遷移後仍正確
  • 避免依賴 Request 對象(可能未初始化)

完整 UploadAction 代碼

package com.example.action;

import java.io.File;
import java.io.IOException;
import javax.servlet.ServletContext;
import org.apache.commons.io.FileUtils;
import org.apache.struts2.util.ServletContextAware;
import com.opensymphony.xwork2.ActionSupport;

public class UploadAction extends ActionSupport implements ServletContextAware {
    private static final long serialVersionUID = 1L;
    
    private File source;
    private String sourceFileName;
    private String sourceContentType;
    private ServletContext context;
    
    // ServletContextAware 接口方法
    @Override public void setServletContext(ServletContext context) { this.context = context; }
    public ServletContext getContext() { return context; }
    public void setContext(ServletContext context) { this.context = context; }
    
    // 文件屬性 getter/setter 省略...
    
    @Override
    public String execute() throws IOException {
        String path = context.getRealPath("/upload");
        File saveDir = new File(path);
        if (!saveDir.exists()) saveDir.mkdirs();
        
        File saveFile = new File(saveDir, sourceFileName);
        FileUtils.copyFile(source, saveFile);
        
        return SUCCESS;
    }
}

結果頁面 uploadResult.jsp

<%@ taglib uri="/struts-tags" prefix="s" %>
<p>文件名:<s:property value="sourceFileName" /></p>
<p>文件類型:<s:property value="sourceContentType" /></p>
<p>文件:<a href="upload/<s:property value="sourceFileName" />">
    <s:property value="sourceFileName" /></a></p>

生產環境優化清單

  • 使用 UUID 或時間戳重命名文件,避免同名覆蓋與安全風險
  • 上傳目錄設在 Web 根目錄外,通過獨立下載 Action 流式輸出
  • 整合病毒掃描(ClamAV)、圖片壓縮(Thumbnailator)、雲存儲
  • 配置 struts.multipart.parser 使用 Jakarta Stream 解析器提升大文件效能
  • 異步上傳:前端分片上傳 + 後端合併,支援斷點續傳
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved