Struts 2 基於 Commons FileUpload 實現文件上傳:
<dependencies>
<!-- Struts 2 核心 -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.0.6</version>
</dependency>
<!-- 文件上傳必需 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head><title>Struts 2 文件上傳</title></head>
<body>
<s:form action="fileUpload" method="POST" enctype="multipart/form-data">
<s:file name="myFile" label="圖片文件" />
<s:textfield name="caption" label="描述" />
<s:submit value="上傳" />
</s:form>
</body>
</html>
關鍵點:enctype="multipart/form-data"、<s:file> 標簽綁定 name="myFile"
package tutorial;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.ServletActionContext;
import java.io.*;
public class FileUploadAction extends ActionSupport {
// 必須的三個屬性(命名約定:字段名、字段名FileName、字段名ContentType)
private File myFile;
private String myFileFileName;
private String myFileContentType;
private String caption; // 額外表單字段
// 業務屬性
private String savePath = "/uploads"; // 相對路徑
private long maxSize = 10 * 1024 * 1024; // 10MB
private String[] allowedTypes = {"image/jpeg", "image/png", "image/gif"};
@Override
public String execute() throws Exception {
// 1. 校驗文件存在
if (myFile == null) {
addFieldError("myFile", "請選擇文件");
return INPUT;
}
// 2. 校驗文件大小
if (myFile.length() > maxSize) {
addFieldError("myFile", "文件過大,最大 " + maxSize/1024/1024 + "MB");
return INPUT;
}
// 3. 校驗文件類型
boolean allowed = false;
for (String type : allowedTypes) {
if (type.equals(myFileContentType)) {
allowed = true;
break;
}
}
if (!allowed) {
addFieldError("myFile", "不支持的文件類型");
return INPUT;
}
// 4. 生成唯一文件名防衝突
String ext = myFileFileName.substring(myFileFileName.lastIndexOf("."));
String newFileName = System.currentTimeMillis() + "_" + UUID.randomUUID().toString().substring(0, 8) + ext;
// 5. 確保保存目錄存在
String realPath = ServletActionContext.getServletContext().getRealPath(savePath);
File destDir = new File(realPath);
if (!destDir.exists()) destDir.mkdirs();
// 6. 保存文件(使用流複製,避免內存溢出)
File destFile = new File(destDir, newFileName);
try (InputStream is = new FileInputStream(myFile);
OutputStream os = new FileOutputStream(destFile)) {
byte[] buffer = new byte[8192];
int len;
while ((len = is.read(buffer)) > 0) {
os.write(buffer, 0, len);
}
}
// 7. 記錄業務信息(可存入數據庫)
System.out.println("上傳成功: " + newFileName + ", 描述: " + caption);
return SUCCESS;
}
// Getter/Setter 省略...
}
<package name="default" extends="struts-default">
<action name="fileUpload" class="tutorial.FileUploadAction">
<interceptor-ref name="defaultStack">
<param name="fileUpload.maximumSize">10485760</param> <!-- 10MB -->
<param name="fileUpload.allowedTypes">image/jpeg,image/png,image/gif</param>
</interceptor-ref>
<result name="success">/upload_success.jsp</result>
<result name="input">/FileUpload.jsp</result>
</action>
</package>
| 參數 | 說明 | 默認值 |
|---|---|---|
| maximumSize | 最大文件大小(字節) | 2MB |
| allowedTypes | 允許的 MIME 類型,逗號分隔 | 無限制 |
| allowedExtensions | 允許的擴展名,逗號分隔 | 無限制 |
// JSP
<s:file name="files" label="文件1" />
<s:file name="files" label="文件2" />
// Action
private List<File> files;
private List<String> filesFileName;
private List<String> filesContentType;
// 自定義 Interceptor 繼承 FileUploadInterceptor
// 重寫 saveFile() 直接流式寫入目標位置
FileUploadInterceptor 進度監聽| 現象 | 原因 | 解決 |
|---|---|---|
| myFile 為 null | 表單缺少 enctype 或 name 不匹配 | 檢查 enctype="multipart/form-data"、name 一致性 |
| 上傳大文件失敗 | 超過 maximumSize 或請求超時 | 調大 maximumSize、增加請求超時時間 |
| 中文文件名亂碼 | 編碼不一致 | 確保 JSP、Action、Server 統一 UTF-8 |
| 臨時文件未刪除 | 異常中斷或配置錯誤 | 配置定時清理任務、使用 try-with-resources |
Struts 2 文件上傳通過攔截器實現聲明式綁定,掌握三屬性約定、校驗邏輯、安全配置,即可構建健壯的上傳功能。