struts1的下载(转)

  • Post author:
  • Post category:其他


上个星期,要做一个利用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()>

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



版权声明:本文为dong342492715原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。