struts1的下载

上个星期,要做一个利用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方法的最后却被注明

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


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


方法2 以前单独在jsp中,这种方法可能挺流行的,不过在action中一样行不通。 例如代码
Java代码 
<pre name="code" class="java">
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;  
            }  
  
}
</pre> 
  
     解释1  为什么成功后return null   因为前面response 已经提交过,没办法再forward,否则报错
     解释2  为什么FileNotFoundException转到error画面,因为对话框中,用户如果点取消按钮,tomcat会报ClientAbortException
假如连这个exception都抓掉,然后进行forward,一样会报response已经提交过的错误,根本无法转向。所以干脆就留
着它好了。
     方法1  其实根方法3一样,输入流,输出流,有兴趣地可以用IOUtils.copy(in, response.getOutputStream());
没兴趣的可以参照以下代码,我也是参考论坛上一位兄弟的

Java代码 
 

Java代码 
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
Java代码 
<script type="text/javascript">  
  
 function download() {    
    window.location ="download.do?method=action2&filePath="+"<bean:write name="filePath" />";  
 }  
</script>  
</head>  
<body onload=download()>  


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

你可能感兴趣的:(struts1)