Struts2 对文件的上传和下载提供了很好的支持,上传时直接用 java.io.File 来接收,下载时也无需自己去设置相应的 Stream 响应头,它提供了 org.apache.struts2.dispatcher.StreamResult 给 Action 使用。它反映到 struts.xml 配置里就是type="stream" 的 result,由 result 去负责把文件内容写入响应中去。Action 的执行方法在 result 之前执行,所以你可以借此控制下载权限,本文也演示了如何判断文件是否存在,不存在则导向到 FileNotFound 页面。StreamResult 中有哪些相关的配置参数可以参考它的源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class StreamResult extends StrutsResultSupport { private static final long serialVersionUID = -1468409635999059850L; protected static final Logger LOG = LoggerFactory.getLogger(StreamResult.class); public static final String DEFAULT_PARAM = "inputName"; protected String contentType = "text/plain"; protected String contentLength; protected String contentDisposition = "inline"; protected String contentCharSet ; protected String inputName = "inputStream"; protected InputStream inputStream; protected int bufferSize = 1024; protected boolean allowCaching = true; ....................... |
下面是一个文件下载的例子:
struts.xml
1 2 3 4 5 6 7 8 9 10 |
<action name="down/pro" method="down"> <param name="fileDir">c:/downloads/</param> <result name="fileNotFound">errors/page_404.html</result> <result type="stream"> <param name="contentType">application/pdf</param> <param name="inputName">targetFile</param> <param name="contentDisposition">filename="${fileName}"</param> <param name="buttferSize">4096</param> </result> </action> |
说明:
1. fileDir 属性设置到 Action 的 fileDire 字段上,标识文件所处的目录。
2. fileNotFound result 是在文件找不到时转向的页面
3. inputName 用于指定待下载文件输入流的名称,即对应于 Action 的属性名;默认为 inputStream,这里定义为 targetFile,所
以 StreamResult 会调用 Action 的 getTargetFile() 方法。
4. ${fileName} 会被这里的 Action 的 fileName 属性替代,它是个 OGNL。
5. 其他的配置看 StreamResult 的源码了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
DownloadAction.java package cc.unmi.download; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import com.opensymphony.xwork2.ActionSupport; public class DownloadAction extends ActionSupport{ private String fileDir; private String fileName; public InputStream getTargetFile() { try { String filePath = fileDir + fileName; return new FileInputStream(filePath); } catch (FileNotFoundException e) { e.printStackTrace(); } return null; } public String down(){ //这里判断文件存不存在,不存在则转向到 fileNotFound 页面 String filePath = fileDir + fileName; if(!new File(filePath).exists()){ return "fileNotFound"; } //由 StreamResult 来处理后续的部分了 return SUCCESS; } public String getFileDir() { return fileDir; } public void setFileDir(String fileDir) { this.fileDir = fileDir; } public void setFileName(String fileName) { this.fileName = fileName; } public String getFileName() { return fileName; } } |
如果文件不存,getTargetFile() 里出现异常,在页面中将会打出:
Struts Problem Report
Struts has detected an unhandled exception:
Messages: Can not find a java.io.InputStream with the name [targetFile] in the invocation stack. Check the tag
specified for this action.
File: org/apache/struts2/dispatcher/StreamResult.java
Line number: 237
--------------------------------------------------------------------------------
Stacktraces
java.lang.IllegalArgumentException: Can not find a java.io.InputStream with the name [targetFile] in the invocation
stack. Check the tag specified for this action.
org.apache.struts2.dispatcher.StreamResult.doExecute(StreamResult.java:237)
org.apache.struts2.dispatcher.StrutsResultSupport.execute(StrutsResultSupport.java:186)
com.opensymphony.xwork2.DefaultActionInvocation.executeResult(DefaultActionInvocation.java:373)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:277)
getTargetFile() 会在 down() 后由 StreamResult 调用,所以可在 down() 中判断文件不存在就 return "fileNotFound";
本文链接 https://yanbin.blog/struts2-download-file-not-found/, 来自 隔叶黄莺 Yanbin Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
感谢博主提供的解决思路~
:)