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

Struts 1 文件上傳完整實戰:從表單到 Action 的完整流程解析

     編輯:Java 相關知識

前言

Struts 1 雖然歷史悠久,但其文件上傳機制通過封裝 Commons FileUpload,提供了相對簡潔的 API。本文通過完整示例解析 Struts 1 文件上傳的核心組件、配置要點與代碼實現。

核心組件

  • <html:file>:JSP 標籤,生成 <input type="file">,property 對應 ActionForm 屬性。
  • org.apache.struts.upload.FormFile:封裝上傳文件的接口,提供 getInputStream(), getFileName(), getFileSize() 等方法。
  • multipart/form-data:表單 enctype 必須設置為此值。

完整代碼實現

1. 上傳頁面 sh.jsp

<%@ taglib uri="https://jakarta.apache.org/struts/tags-html" prefix="html"%>
<html:form action="/jsp/upload.do" method="post" enctype="multipart/form-data">
    <html:file property="photo"/>
    <html:submit value="上傳"/>
</html:form>

2. FormBean:UploadForm.java

package com.zyy.struts.form;
import org.apache.struts.action.ActionForm;
import org.apache.struts.upload.FormFile;

public class UploadForm extends ActionForm {
    private FormFile photo;
    // getter/setter 省略
}

3. 工具類:IPTimeStamp.java(生成唯一文件名)

package com.zyy.util;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

public class IPTimeStamp {
    private String ip;
    public IPTimeStamp(String ip) { this.ip = ip; }
    public String getIPTimeRand() {
        StringBuffer buf = new StringBuffer();
        if (ip != null) {
            for (String s : ip.split("\\.")) buf.append(addZero(s, 3));
        }
        buf.append(new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()));
        for (int i=0; i<3; i++) buf.append(new Random().nextInt(10));
        return buf.toString();
    }
    private String addZero(String str, int len) {
        StringBuffer s = new StringBuffer(str);
        while (s.length() < len) s.insert(0, "0");
        return s.toString();
    }
}

4. Action:UploadAction.java

package com.zyy.struts.action;
import java.io.*;
import javax.servlet.http.*;
import org.apache.struts.action.*;
import com.zyy.struts.form.UploadForm;
import com.zyy.util.IPTimeStamp;

public class UploadAction extends Action {
    public ActionForward execute(ActionMapping mapping, ActionForm form,
                                 HttpServletRequest request, HttpServletResponse response) throws Exception {
        UploadForm uploadForm = (UploadForm) form;
        FormFile photo = uploadForm.getPhoto();

        // 1. 生成唯一文件名:IP+時間戳+隨機數 + 原始擴展名
        String ext = photo.getFileName().substring(photo.getFileName().lastIndexOf("."));
        String fileName = new IPTimeStamp(request.getRemoteAddr()).getIPTimeRand() + ext;

        // 2. 目標目錄:應用根目錄下的 upload 資料夾
        String realPath = getServlet().getServletContext().getRealPath("/") + "upload" + File.separator;
        File dir = new File(realPath);
        if (!dir.exists()) dir.mkdirs();

        // 3. 流式寫入
        File outFile = new File(realPath + fileName);
        try (InputStream in = photo.getInputStream();
             OutputStream out = new FileOutputStream(outFile)) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = in.read(buffer)) != -1) out.write(buffer, 0, len);
        }

        return null; // 無需跳轉,或按需返回 mapping.findForward("success")
    }
}

5. Struts 配置:struts-config.xml

<form-beans>
    <form-bean name="uploadForm" type="com.zyy.struts.form.UploadForm"/>
</form-beans>

<action-mappings>
    <action path="/jsp/upload"
            type="com.zyy.struts.action.UploadAction"
            name="uploadForm"
            scope="request"
            input="/jsp/sh.jsp">
    </action>
</action-mappings>

關鍵技術點深度解析

1. 文件上傳三要素

  1. Form method="post"
  2. Form enctype="multipart/form-data"
  3. 存在 <input type="file"> 欄位

2. FormFile 核心方法

  • getInputStream():獲取文件內容流
  • getFileName():原始文件名(含路徑,需處理)
  • getFileSize():文件大小(字節)
  • getContentType():MIME 類型
  • destroy():釋放臨時文件資源(重要!)

3. 臨時文件與內存閾值

Struts 1 / Commons FileUpload 預設將小文件存內存,大文件寫臨時目錄。可在 struts-config.xml 的 <controller> 中配置:

<controller maxFileSize="10M" tempDir="/tmp/upload" />

4. 文件名衝突處理

示例採用 IP+毫秒時間戳+3位隨機數 策略,極大降低衝突概率。生產環境建議加入 UUID 或分布式 ID。

常見問題與避坑

  1. 文件名亂碼:瀏覽器提交文件名編碼不一,建議用 new String(name.getBytes("ISO-8859-1"), "UTF-8") 轉碼。
  2. 大文件上傳失敗:檢查 maxFileSize、Tomcat maxPostSize、磁盤空間。
  3. 資源洩漏:必須在 finally 塊關閉流、調用 FormFile.destroy()。
  4. 路徑遍歷攻擊:嚴禁直接使用用戶提交的文件名,必須重命名。

總結

Struts 1 文件上傳本質是對 Commons FileUpload 的封裝,核心流程為:JSP 表單 → FormFile 封裝 → Action 流式存儲。掌握 FormFile API、enctype 設置、文件命名策略與資源釋放是穩健實現的關鍵。雖然 Struts 1 已退出歷史舞台,但其設計思想對理解現代框架(Spring MVC, Struts 2)文件上傳機制仍有參考價值。

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