struts1.x文件下载

上个星期,要做一个利用struts1.x作文件下载功能的网页,要求点击链接后,开始弹出下载对话框,下载成功后,转向成功信息页面,失败后,转向error信息页面。

于是找啊找,单纯的文件下载功能还是挺容易的,既可以自己写,也可以用类似smartupload这类现成的包。 至于为什么不用直接的链接,是为了防止服务器文件结构泄漏,有心人其他文件也可以随意下载,那岂不是麻烦?

 如果要自己写得话,action的写法大致有三 1, 用输入流,输出流 2, 用dispatcher 3, 用downloadAction

方法3是struts推荐的官方写http://wiki.apache.org/struts/StrutsFileDownload 写的时候,只要继承downloadAction类,然后重写getStreamInfo方法就可以了。但是看一下这个类的src http://www.docjar.org/html/api/org/apache/struts/actions/DownloadAction.java.html 就明白,这个类的getStreamInfo会把结果传给execute方法,而execute方法的最后却被注明

 

// Tell Struts that we are done with the response.
return null;

 

 

意味着根本不可能做任何转向。至于试着再重写一下execute方法,好像没有人这么办,在google.com上以关键字downloadAction redirect 或者downloadAction foward,也没有任何可以有用的结果,所以首先放弃了这个方法。不过这个方法还是最简单最可靠的,仿照它给的例子,几行代码就完事,真好。

 

 

方法2 以前单独在jsp中,这种方法可能挺流行的,不过在action中一样行不通。 例如代码

public ActionForward execute(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)  {
			FileDownLoadForm fdform =(FileDownLoadForm)form;
			String path = fdform.getFilePath();
		
		    response.setContentType("application/x-download");
		    String filenamedownload = path;
		    String filenamedisplay = path.substring(path.lastIndexOf("/")+1);
		    
		    try {
		    	filenamedisplay = URLEncoder.encode(filenamedisplay,"UTF-8");
				response.addHeader("Content-Disposition","attachment;filename=" + filenamedisplay);
		        RequestDispatcher dispatcher = request.getRequestDispatcher(filenamedownload);
		        if(dispatcher != null)
		        {
		            dispatcher.forward(request,response);
		        }
		        response.flushBuffer();

		       return null ;
		       //  return mapping.findForward("success");
		    }catch(FileNotFoundException e){
				e.printStackTrace();       	
				return mapping.findForward("error");
			}catch(Exception e){
				e.printStackTrace();
				return null;
			}

}
 

     解释1  为什么成功后return null   因为前面response 已经提交过,没办法再forward,否则报错

     解释2  为什么FileNotFoundException转到error画面,因为对话框中,用户如果点取消按钮,tomcat会报ClientAbortException

假如连这个exception都抓掉,然后进行forward,一样会报response已经提交过的错误,根本无法转向。所以干脆就留

着它好了。

     方法1  其实根方法3一样,输入流,输出流,有兴趣地可以用IOUtils.copy(in, response.getOutputStream()); 

 没兴趣的可以参照以下代码,我也是参考论坛上一位兄弟的

 

   		

 

public ActionForward execute(ActionMapping mapping, ActionForm form,
	            HttpServletRequest request, HttpServletResponse response)  {
			
			FileDownLoadForm fdform =(FileDownLoadForm)form;
			String path = fdform.getFilePath();
			
			BufferedInputStream   bis = null;
			BufferedOutputStream  bos = null;
			InputStream fis = null;
			OutputStream fos = null;
			
			try{

				File uploadFile = new File(path);

		
				fis = new FileInputStream(uploadFile);
				bis = new BufferedInputStream(fis);
				fos = response.getOutputStream();
				bos = new BufferedOutputStream(fos);
				


				response.reset();
				response.setHeader("Content-disposition", "attachment;filename =" + URLEncoder.encode(path.substring(path.lastIndexOf("/")+1), "utf-8"));


				int bytesRead = 0;
				byte[] buffer = new byte[4096];
				while((bytesRead = bis.read(buffer,0,4096)) != -1){
					bos.write(buffer, 0, bytesRead);
				}
				bos.flush();
				fis.close();
				bis.close();
				fos.close();
				bos.close();
				//return mapping.findForward("success");
				
				return null;
			}catch(FileNotFoundException e){
				e.printStackTrace();       	
				return mapping.findForward("error");
			}catch(Exception e){
				e.printStackTrace();
				return null;
			}
			
		}

 

 

解释1   为什么要response.reset(); 假如这个方法是写在一个图片的链接上,如果不reset,就没办法多次下载,

不过对我来说现在没什么影响

解释2  对话框那块为什么只显示文件名    开始的时候我把整个路径都写进去了,结果倒也能下载,可使整个文件的路径都暴露了,跟直接用链接没什么区别了,所以一定要只写文件名

 

 

   以上3个方法都不能实现成功后转向成功页面的问题,在javaeye和csdn上询问也没有什么结果,不过我的确是见过类似的网页,不知道他们是怎么完成的?始终疑问阿。

   没有办法,只好考虑作个假的成功画面,用DispatchAction

   一个action1 ,实现转向成功页面功能 ,   一个action 2 ,实现下载功能

   工作流程为  点击链接, 甭管文件存在不存在,直接进入成功画面,在成功画面打开的同时,执行action2

<script type="text/javascript">

 function download() { 	
	window.location ="download.do?method=action2&filePath="+"<bean:write name="filePath" />";
 }
</script>
</head>
<body onload=download()>

 

如果文件找不到,则成功画面会转向到失败画面,否则会留在成功画面并弹出对话框

 

 

 

你可能感兴趣的:(JavaScript,apache,tomcat,bean,struts)