承接上篇,本文深入 Struts 2 文件上傳進階特性:多文件上傳、文件類型/大小限制、錯誤信息國際化,以及基於 stream Result Type 的文件下載實現。
method="post"enctype="multipart/form-data"<input type="file"> 欄位Action 中需聲明三組屬性(名稱固定模式):
| 屬性 | 類型 | 說明 |
|---|---|---|
myFile | File / File[] / List<File> | 上傳文件內容(臨時文件) |
myFileFileName | String / String[] / List<String> | 原始文件名 |
myFileContentType | String / String[] / List<String> | MIME 類型 |
規則:屬性名 對應表單 name,後綴固定為 FileName、ContentType。
<%@ taglib prefix="s" uri="/struts-tags" %>
<s:actionerror/> <s:fielderror/>
<form action="upload1.action" method="post" enctype="multipart/form-data">
用戶名:<input type="text" name="username"/><br/>
靓照:<input type="file" name="photo"/><br/>
<input type="submit" value="上傳"/>
</form>
package com.itheima.actions;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class UploadAction1 extends ActionSupport {
private String username;
private File photo;
private String photoFileName;
private String photoContentType;
// getter/setter 省略
public String upload() {
System.out.println(photoFileName + ":" + photoContentType);
System.out.println(username);
String realPath = ServletActionContext.getServletContext().getRealPath("/images");
File dir = new File(realPath);
if (!dir.exists()) dir.mkdirs();
try {
FileUtils.copyFile(photo, new File(dir, photoFileName));
return SUCCESS;
} catch (IOException e) {
e.printStackTrace();
return ERROR;
}
}
}
<action name="upload1" class="com.itheima.actions.UploadAction1" method="upload">
<interceptor-ref name="defaultStack">
<param name="fileUpload.allowedTypes">image/jpeg,image/png</param>
<param name="fileUpload.allowedExtensions">jpg,jpeg,png</param>
<param name="fileUpload.maximumSize">2097152</param> <!-- 2MB -->
</interceptor-ref>
<result>/success.jsp</result>
<result name="error">/error.jsp</result>
<result name="input">/index.jsp</result> <!-- 驗證失敗返回 -->
</action>
maximumSize:最大字節數,默認 2MBallowedTypes:允許 MIME 類型,逗號分隔allowedExtensions:允許擴展名,逗號分隔超限或類型不匹配會觸發 input 結果,可通過 <s:actionerror/>、<s:fielderror/> 顯示錯誤。
struts.messages.error.uploading=上傳錯誤: {0}
struts.messages.error.file.too.large=上傳文件太大: {0} "{1}" "{2}" {3}
struts.messages.error.content.type.not.allowed=上傳文件類型不允許: {0} "{1}" "{2}" {3}
struts.messages.error.file.extension.not.allowed=上傳文件後綴不允許: {0} "{1}" "{2}" {3}
<constant name="struts.custom.i18n.resources" value="cn.xxx.fileuploadmessage"/>
佔位符含義:{0}=表單字段名,{1}=原始文件名,{2}=臨時文件名,{3}=文件類型/大小。
Action 屬性改為數組或 List:
private File[] photo;
private String[] photoFileName;
private String[] photoContentType;
public String upload() {
// 遍歷數組逐個保存
for (int i = 0; i < photo.length; i++) {
FileUtils.copyFile(photo[i], new File(dir, photoFileName[i]));
}
return SUCCESS;
}
JSP 中放置多個 <input type="file" name="photo"> 即可。
type="stream" 結果類型InputStream 類型屬性(如 image)contentType、contentDisposition、contentLengthpackage com.itheima.actions;
import java.io.*;
import org.apache.commons.io.FilenameUtils;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class DownloadAction extends ActionSupport {
private InputStream image;
private String filename;
private long filesize;
// getter 省略
public String download() throws Exception {
String fileRealPath = ServletActionContext.getServletContext().getRealPath("/WEB-INF/classes/霉女.jpg");
filename = FilenameUtils.getName(fileRealPath);
filesize = new File(fileRealPath).length();
image = new FileInputStream(fileRealPath);
return SUCCESS;
}
}
<action name="download" class="com.itheima.actions.DownloadAction" method="download">
<result type="stream">
<param name="inputName">image</param>
<param name="contentType">application/octet-stream</param>
<!-- OGNL 表達式調用 URLEncoder 靜態方法,需開啟 struts.ognl.allowStaticMethodAccess -->
<param name="contentDisposition">attachment;filename=${@java.net.URLEncoder@encode(filename,'UTF-8')}</param>
<param name="contentLength">${filesize}</param>
</result>
</action>
<constant name="struts.ognl.allowStaticMethodAccess" value="true"/>
inputName 對應 Action 中 InputStream 屬性名contentDisposition: attachment 強制下載而非瀏覽器打開URLEncoder.encode,配合 OGNL 靜態調用contentLength 讓瀏覽器顯示進度條BufferedInputStream 分塊讀取,避免 OOMStruts 2 文件上傳下載核心在於:約定屬性命名 → fileUpload 攔截器參數化配置 → 國際化友好提示 → Stream Result 流式輸出。掌握多文件數組綁定、類型大小限制、中文文件名編碼三大難點,即可應對企業級文件交互場景。