Struts2文件上传下载(二)

如果用户下载的文件是中文名,或者是在下载前检查用户的权限,就要使用Struts2提供的文件下载。在前台页面上提供一个链接,这个链接指向一个存在于服务器上的文件,并且文件的名字是中文名称,对中文名称进行URL编码。以下是download.jsp文件的内容:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@page import="java.net.URLEncoder"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>文件下载</title>
  </head>
  <body>
    <a href="struts2download.action?fileName=<%=URLEncoder.encode("download中文.doc","UTF-8") %>">下载</a>
  </body>
</html>
Action类:

package com.jason.web.action;

import java.io.InputStream;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class DownLoadAction extends ActionSupport{
	private static final long serialVersionUID = -6103161491484708345L;
	
	private String fileName; // 要下载的文件的名称
	private String downDir;// 下载文件夹由struts在配置文件中注入
	private String fileEncoding;// 文件名 字符集
	
//	省略Getter、Setter方法

	public InputStream getDownloadStream() throws Exception {
		// 对于get方式提交的数据需要我们手工进行转码
		fileName = new String(fileName.getBytes("iso-8859-1"), fileEncoding);
		// 取得文件的路径
		String filePath = downDir + "/" + fileName;
//		System.out.println(filePath);
		return ServletActionContext.getServletContext().getResourceAsStream(filePath);
	}
	
	@Override
	public String execute() throws Exception {
		return SUCCESS;
	}
}

struts.xml配置文件

<action name="struts2download" class="com.jason.web.action.DownLoadAction">
			<param name="downDir">/download</param>
			<param name="fileEncoding">UTF-8</param>
			<result type="stream">
				<param name="inputName">downloadStream</param>
				<!--下载文件的缓冲区大小-->
				<param name="bufferSize">4096</param>
				<!--
					如果想让用户直接使用浏览器打开,我们可以直接指定正确的类型。
					如果不好确定类型,可以使用application/octet-stream,表示二进制流
				-->
				<param name="contentType">application/octet-stream;charset=iso-8859-1</param>
				<param name="contentDisposition">attachment;filename="${fileName}"</param>
			</result>
		</action>

运行OK!但是当取消下载时会报错
java.lang.IllegalStateException
异常原因分析:  stream对应的类是org.apache.struts2.dispatcher.StreamResult,该类的处理过程如下:1。配置其中result标签下的各个参数2。从服务器中获取输入流,并同时与客户端建立输出流(服务器与客户端链接通过Socket进行连接)3。当点击“保存”或“打开”时,开始传输数据。如果点击“取消”,关闭所有的流。  这里要注意的是,但是实际发现Socket并没有断开!并且流也没有关闭!这一点非常重要!  所以在JSP容器通过Response获取输出流之前,前面的流并没有关闭,所以会造成该异常的报出。
解决办法:
需要下载struts2-sunspoter-stream-1.0.jar,并复制在/WEB-INF/lib下
struts.xml配置修改如下:
                
<result-types>  
		     <result-type name="streamx" class="com.sunspoter.lib.web.struts2.dispatcher.StreamResultX"/>  
		</result-types>
		<action name="struts2download" class="com.jason.web.action.DownLoadAction">
			<param name="downDir">/download</param>
			<param name="fileEncoding">UTF-8</param>
			<result type="streamx">
				<param name="inputName">downloadStream</param>
				<!--下载文件的缓冲区大小-->
				<param name="bufferSize">4096</param>
				<!--
					如果想让用户直接使用浏览器打开,我们可以直接指定正确的类型。
					如果不好确定类型,可以使用application/octet-stream,表示二进制流
				-->
				<param name="contentType">application/octet-stream;charset=iso-8859-1</param>
				<param name="contentDisposition">attachment;filename="${fileName}"</param>
			</result>
		</action>
只需添加一个result-type,将原有的result中type改为“streamx”,其他一律不变,在这种情况下,点击“取消”的同时也关闭了流,不会再报出该异常。
再点击取消会出现警告
WARN StreamResult:45 - StreamResultX Warn : socket write error 
如果出现该警告说明正确执行,该警告说明,Socket非正常中断,但是流确实已经关闭,自此再也不用看到上面出现的讨厌异常结果。
posted @ 2012-07-16 19:03  問天  阅读(106)  评论(0编辑  收藏  举报