struts2 下载遭遇记 - 点滴记忆*记忆点滴
收藏本站

struts2 下载遭遇记

项目需要个下载功能,因为使用struts2 自然想到使用struts2 的下载。结合百度google 很快完成了一个


public class DownloadAction extends BaseAction{
	 /**
	 * 
	 */
	private static final long serialVersionUID = -3036837032581084659L;
	/**
	 * 下载显示的文件名
	 */
	 private String filename;

	 /**
	  * 下载文件相对路径
	  */
	 private String filepath;
	 
     public void setFilename(String filename) {
             this.filename = filename;
     }
     public void setFilepath(String filepath) {
         this.filepath = filepath;
     }
     public String getFilename() throws 
         return this.filename;
     }
     public InputStream getInputStream() throws FileNotFoundException {
		try {
			return new FileInputStream(new File(GlobalConfig.getRootPath(Basepath.NORMAL_FILE),filepath));
		} catch (Exception e) {
			throw new FileNotFoundException("下载文件不存在 :["+ filepath+"]");
		}
     }
     
     public String execute() throws FileNotFoundException,IllegalAccessException{
    	if(filepath == null){
    		throw new FileNotFoundException("下载文件不存在 :["+ filepath+"]");
    	}
    	String md5 = Encodes.md5(filepath);
		String path = (String) ActionContext.getContext().getSession()
							.get(md5);
		if(path == null || !filepath.equals(path)){
				throw new IllegalAccessException("您没有权限下载该文件!");
		}
		ActionContext.getContext().getSession().put(md5,null);
       return SUCCESS;
 }
}
配置方式:
<global-results>
     <result name="globalDownLoad" type="redirectAction">	
		  <param name="actionName">download</param>
		  <param name="filename">${filename}</param>
		  <param name="filepath">${filepath}</param>
		  <param name="namespace">/</param>
     </result>
</global-results>


<action name="download" class="com.ichangyan.tsp.common.action.DownloadAction">
           <result type="stream">
                  <param name="contentType">application/octet-stream;charset=ISO8859-1</param>
                  <param name="inputName">inputStream</param>
                  <param name="contentDisposition">attachment;filename="${filename}"</param>
                  <param name="bufferSize">4096</param>
           </result>
  </action>


为了下载安全考虑,所有的下载都需先经过具体业务的action,设置md5,filename,filepath 然后跳转全局result,chrome 测试一切OK.


没两天,测试反应,ie 下载中文名乱码。乱码以前用struts1 下载时遇到过。设置response 编码即可,但很遗憾失败了。百度了一下,各种方式,都没有一次成功,但发现段原理ie 需要urlEncode,chrome 需要ISO8859-1,自己调。

getFilename 中增加编码处理逻辑:

ServletActionContext.getResponse().setHeader("charset","charset=ISO8859-1");
    	 HttpServletRequest request = ServletActionContext.getRequest();  
         String Agent = request.getHeader("User-Agent");  
         if (null != Agent) {  
             Agent = Agent.toLowerCase();  
             if (Agent.indexOf("msie") != -1) { 
                 filename = java.net.URLEncoder.encode(filename,"ISO8859-1");  
             }
         }
         return this.filename;

测试OK, Ie chrome 都没有问题了。

但没高兴多久,测试报告 360 下载失败,原因没有权限。分析原因发现360 请求了两次,第二次直接请求下载action,这时session 中MD5已经删除了,肯定下载失败。继续百度,发现确实有人反应这个问题,还有人在360 论坛反应,还有“工作人员” 在处理。但看来仍没有处理完成。分析了原理,360 对待重定向的下载,使用了专门下载工具,将重定向地址截取放到了下载工具进行二次请求。网友建议解决方案:  alert("对不起,不支持小众浏览器");

笑话笑完了问题还得解决,谁让人家推广的好,好多小白都用呢。仔细分析,既然是拦截重定向地址,那好不给你重定向,直接转发。

    留下足迹