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("对不起,不支持小众浏览器");
笑话笑完了问题还得解决,谁让人家推广的好,好多小白都用呢。仔细分析,既然是拦截重定向地址,那好不给你重定向,直接转发。