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

Struts2 文件上傳下載完整實戰:大文件處理、類型限制、異常攔截

     編輯:Java 相關知識

文件上傳

Action 基類屬性

public class BaseAction extends ActionSupport {
    protected List upload;              // 上傳文件
    protected List uploadContentType; // MIME 類型
    protected List uploadFileName;    // 原始文件名
    protected String savePath;                // 保存目錄(struts.xml 注入)
    // getter/setter 省略
}

上傳方法

public void uploadFiles() {
    if (upload != null) {
        for (int i = 0; i < upload.size(); i++) {
            File src = upload.get(i);
            String destName = uploadFileName.get(i);
            File dest = new File(savePath, destName);
            try (FileInputStream fis = new FileInputStream(src);
                 FileOutputStream fos = new FileOutputStream(dest)) {
                byte[] buf = new byte[1024];
                int len;
                while ((len = fis.read(buf)) > 0) fos.write(buf, 0, len);
            } catch (IOException e) {
                addActionError("文件 " + destName + " 保存失敗");
            }
        }
    }
}

struts.xml 關鍵配置

<package name="default" extends="struts-default">
    <!-- 全局上傳限制 -->
    <constant name="struts.multipart.maxSize" value="52428800" /> <!-- 50MB -->
    <constant name="struts.multipart.saveDir" value="/tmp/uploads" />

    <action name="itemRDAction_*" class="itemRDAction" method="{1}">
        <param name="savePath">/data/uploads</param>
        <interceptor-ref name="defaultStack">
            <param name="fileUpload.allowedTypes">
                image/jpeg,image/png,image/gif,
                application/pdf,
                application/msword,
                application/vnd.openxmlformats-officedocument.wordprocessingml.document,
                application/vnd.ms-excel
            </param>
            <param name="fileUpload.maximumSize">20971520</param> <!-- 20MB -->
        </interceptor-ref>
        <result name="input">/error/upload-error.jsp</result>
        <result name="success">/success.jsp</result>
    </action>
</package>

大文件優化與異常處理

  • struts.multipart.maxSize(全局)必須 ≥ Action 級 maximumSize,否則請求到達 Action 前被容器拒絕,拋出 SizeLimitExceededException。
  • 在自定義 BaseAction 重寫 addActionError 友好提示:
@Override
public void addActionError(String msg) {
    if (msg.contains("exceeds the configured maximum")) {
        // 解析實際大小與限制大小
        Pattern p = Pattern.compile("(\\d+)");
        Matcher m = p.matcher(msg);
        long actual = m.find() ? Long.parseLong(m.group()) : 0;
        long limit = m.find() ? Long.parseLong(m.group()) : 0;
        super.addActionError(String.format("上傳文件 %.2f MB 超過限制 %.2f MB", actual/1048576.0, limit/1048576.0));
    } else {
        super.addActionError(msg);
    }
}
  • 頁面用 <s:fielderror/> 顯示,或 AJAX 返回 JSON 彈窗。

文件下載

DownloadAction (Stream Result)

@Controller("downloadAction")
@Scope("prototype")
public class DownloadAction extends BaseAction {
    private String filename;
    private InputStream inputStream;
    private String mimeType;

    public InputStream getInputStream() {
        try {
            String path = savePath + "/" + new String(filename.getBytes("ISO-8859-1"), "UTF-8");
            mimeType = ServletActionContext.getServletContext().getMimeType(path) + ";charset=UTF-8";
            inputStream = new FileInputStream(path);

            String agent = ServletActionContext.getRequest().getHeader("User-Agent");
            if (agent != null) {
                if (agent.contains("Firefox")) {
                    mimeType = mimeType.replace("UTF-8", "ISO-8859-1");
                } else { // IE/Edge/Chrome
                    filename = java.net.URLEncoder.encode(filename, "UTF-8");
                }
            }
        } catch (Exception e) {
            log.error("下載準備失敗", e);
        }
        return inputStream;
    }

    public String execute() { return SUCCESS; }
    // getter/setter 省略
}

struts.xml 下載配置

<action name="download" class="downloadAction">
    <param name="savePath">/data/uploads</param>
    <result type="stream">
        <param name="contentType">${mimeType}</param>
        <param name="contentDisposition">attachment;filename="${filename}"</param>
        <param name="inputName">inputStream</param>
        <param name="bufferSize">4096</param>
    </result>
</action>

前端下載鏈接

<c:if test="${not empty item.accessory}">
    <a href="download.action?filename=${item.accessory}">下載</a>
</c:if>

核心參數關係圖

參數作用域建議值說明
struts.multipart.maxSize全局≥ 最大業務文件容器級限制,超過直接拒絕請求
fileUpload.maximumSizeAction/攔截器業務允許最大攔截器級限制,超過返回 input 結果
fileUpload.allowedTypesAction/攔截器MIME 列表類型白名單,不匹配返回 input
struts.multipart.saveDir全局臨時目錄上傳文件落盤臨時目錄,處理完需移動/刪除

常見坑點總結

  1. 表單必須 enctype="multipart/form-data",否則進入 input 結果且無文件對象。
  2. 最大值層級:容器 (Tomcat maxPostSize) → struts.multipart.maxSize → fileUpload.maximumSize,由外向內遞減。
  3. 編碼處理:下載文件名跨瀏覽器需區分 Firefox (ISO-8859-1) 與其他 (UTF-8 + URLEncoder)。
  4. 臨時文件清理:上傳失敗/異常時,saveDir 遺留文件需定時清理任務。
  5. 大文件內存:Struts2 默認將上傳文件寫入臨時文件而非內存,但 maximumSize 仍限制臨時文件大小。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved