Struts2 通過 Result Type = "stream" 實現文件下載,關鍵在於:
InputStream getInputStream() 返回文件流。String getDownloadFileName() 返回經編碼的文件名,解決中文亂碼。struts.xml 中配置 contentDisposition 為 attachment;filename="${downloadFileName}"。package com.example.action;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.ServletActionContext;
import javax.servlet.ServletContext;
import java.io.*;
public class DownloadAction extends ActionSupport {
private static final long serialVersionUID = 1L;
// 前端傳入的相對路徑(如 /upload/xxx.pdf)
private String inputPath;
// 前端傳入的文件名(含中文)
private String fileName;
public String downloadFile() throws Exception {
ServletContext context = ServletActionContext.getServletContext();
String baseDir = context.getRealPath("/upload");
String targetFile = context.getRealPath(inputPath);
// 安全校驗:防止目錄遍歷攻擊
if (!targetFile.startsWith(baseDir)) {
return null; // 或拋出異常
}
return SUCCESS; // 對應 struts.xml 中 name="success"
}
// 供 Stream Result 讀取的輸入流
public InputStream getInputStream() throws UnsupportedEncodingException {
// 關鍵:ISO-8859-1 → UTF-8 轉碼,修正中文路徑
String decodedName = new String(fileName.getBytes("ISO-8859-1"), "UTF-8");
String fullPath = inputPath + File.separator + decodedName;
return ServletActionContext.getServletContext().getResourceAsStream(fullPath);
}
// 供 Content-Disposition 使用的下載文件名
public String getDownloadFileName() throws UnsupportedEncodingException {
// 瀏覽器兼容性編碼:這裡採用 ISO-8859-1,亦可根據 User-Agent 做更細緻處理
return new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
}
// Getter/Setter 省略
public String getInputPath() { return inputPath; }
public void setInputPath(String inputPath) { this.inputPath = inputPath; }
public String getFileName() { return fileName; }
public void setFileName(String fileName) { this.fileName = fileName; }
}
<%@ taglib prefix="s" uri="/struts-tags" %>
<ul>
<li><a href="<s:url action='downloadFile' namespace='/download'><s:param name='fileName'>dwr.jar</s:param></s:url>">dwr.jar 下載</a></li>
<li><a href="<s:url action='downloadFile' namespace='/download'><s:param name='fileName'>Struts2教程.pdf</s:param></s:url>">Struts2教程.pdf 下載</a></li>
</ul>
<package name="download" namespace="/download" extends="struts-default">
<action name="downloadFile" class="com.example.action.DownloadAction" method="downloadFile">
<param name="inputPath">/upload</param>
<result name="success" type="stream">
<param name="contentType">application/octet-stream</param>
<param name="inputName">inputStream</param>
<param name="contentDisposition">attachment;filename="${downloadFileName}"</param>
<param name="bufferSize">4096</param>
</result>
</action>
</package>
關鍵屬性說明:
inputName:對應 Action 中 getInputStream() 方法(去掉 get 首字母小寫)。contentDisposition:attachment 強制下載;filename 取自 getDownloadFileName()。bufferSize:緩衝區大小,建議 4096 或 8192 提升大文件傳輸效能。不同瀏覽器對 Content-Disposition 編碼解析不一,生產環境建議使用 HttpServletResponse.setHeader 配合 URLEncoder.encode(fileName, "UTF-8") 並處理 User-Agent 差異,或引入 Content-Disposition 處理工具類(如 Spring 的 ContentDisposition)。
掌握 Stream Result 機制與編碼轉換細節,即可在 Struts2 中穩健實現含中文文件名的下載功能。