zoukankan      html  css  js  c++  java
  • 关于文件下载

    文件下载,可以通过Servlet中的写法,也可以通过Struts框架做。已经做过这个功能很多次了。用的多了,这次突然发现了一个问题。

    在项目中,做了一个下载功能,在好几个页面都用了这个功能,相同的方法,在不同页面引用。

    调用这个功能,用URL重写的方式调用action中的方法。 

    这里的下载功能没有使用struts框架,用的servlet中的

     一、探索过程

    (1)刚开始我以为,在不同页面上调用这个方法,方法虽然相同,但调用方法后回到的页面不同。所以我把这个公用的方法提出来,作为action中private方法,不同页面请求Action中的不同方法,这些方法都调用这个private方法,这些action返回值回到各自的页面。但后来证明不需要这么麻烦。就把这个称为方法一。

    (2)然后我觉得方法一太麻烦了。想把下载方法放到action中,然后在页面上用ajax访问这个action中的方法。不同的页面都走同样的ajax请求,这样,这个方法就复用了。因为项目框架中用的是dwr。所以我也直接用dwr发送这个请求了。写完之后,下载功能报错。调试后发现,是在HttpServletResponse response=ActionContext.getHttpServletResponse();时报的错response获取不到,后来我换成ResponseAware注入到Action中的方式获取response,还是获取不到,response为null。上网查原因,网上是这么说的:

      Action中获取response有两种方式:ActionContext.getHttpServletResponse()和ResponseAware注入。只有当请求通过struts.xml文件时,才能获取到response。

    因为dwr并没有走struts.xml,而是通过自己的配置文件dwr.xml,所以通过dwr向action发送请求,是获取不到response的。没有response也就无法使用FileOutputStream out=response.getOutputStream();没有输出流,文件下载就失败。就把这个失败的方法称为方法二吧。

    (3)既然dwr不行,然后我就想换成jQuery来做这个ajax效果。jQuery中ajax请求是走struts.xml的,获取response肯定没问题。把这个还未用实践尝试的方法称为方法三。

    (4)中间和同事说了,他也是突然一愣。我俩讨论了下,发现:

    action中下载的方法,代码大致如下:

     1 public String downloadFile(){
     2     //要下载的文件
     3     File file = new File("F:/upload/课程.png");
     4     //说明下载文件的类型
     5     resp.setContentType("image/png");//应该写一个工具类或方法,根据文件名后缀,获得文件MIME类型
     6     //说明下载文件的长度,进度条,以便用户看下载进度
     7         resp.setContentLength(Long.valueOf(file.length()).intValue());
     8     //文件名有中文时,为了在弹出的保存框中显示中文,转码。浏览器会相反方向转码,即ISO8859-1→UTF-8
     9     String fileName=new String("1.png".getBytes("UTF-8"),"ISO8859-1");
    10     //出现弹出框,并显示下载的文件名
    11     resp.setHeader("Content-Disposition", "attachment;filename=""+fileName+""");//响应头
    12         
    13     InputStream inputStream = new FileInputStream(file);
    14     //获得响应输出流,输出到网页上
    15     OutputStream outputStream =resp.getOutputStream();//返回ServletOutputStream
    16         
    17     BufferedOutputStream bos=new BufferedOutputStream(outputStream);
    18     BufferedInputStream bis=new BufferedInputStream(inputStream);
    19         
    20     byte[] buffer=new byte[100];//缓冲区大小影响下载速度
    21     int len=-1;
    22         
    23     while((len=bis.read(buffer))!=-1){
    24         bos.write(buffer, 0, len);
    25     }
    26     bos.flush();
    27     bos.close();
    28     bis.close();
    29         
    30     System.out.println("下载完成!");
    31     
    32     return null;  
    33 }
    View Code

    执行下载程序的时候,方法可以返回null或者没有返回值。下载程序返回null或者没有返回值的时候,不用给struts.xml中的action配置<result>,下载之后,页面也不会跳转,仍然保持在原页面。所以,action中的这个方法是可以在系统中的不同页面上直接调用的,这个方法也不用再像上面那样各种处理,直接调用就行了。如:

    1 <input type="button" onclick="download('${ctx}',${id});" value="下载" />
    1 function download(ctx,id){
    2     location.href=ctx+"/doActivity/downloadFile.do?id="+id;
    3 }
    1 <action name="downloadFile" class="activityOrganAction" method="downloadFile">
    2 </action>

    除了Ajax的请求,这个方法和方法三几乎没有什么不同。

    二、总结

    当:多个页面共用一个下载方法,方法后台没有返回值或者返回null,那么在struts.xml中不用配置<result>,下载之后页面会停留在当前页面,不会跳转。在这些页面可以直接调用这同一个下载方法。

    代码写久了,下载的方法用多了,慢慢也就在这些细节上模糊了,这次算是弄清楚这个问题了。

    2018.4.2

    action属于MVC的C层,公用的部分不适合在这里做公共的。

    下载的方法属于共用方法,这里用的是servlet,可以抽出来放到工具类中,如PubMethod,或PubUtil,由各个action调用,把file传参。

  • 相关阅读:
    SSH Secure File Transfer上传文件错误:encountered 1 errors during the transfer解决办法
    出现Unrecognized field "state" (class com.jt.manage.pojo.ItemCat)异常
    (error) DENIED Redis is running in protected mode because protected mode is enabled
    错误:在maven install是抛出 “1.5不支持diamond运算符,请使用source 7或更高版本以启用diamond运算符”
    Java实现POI读取Excel文件,兼容后缀名xls和xlsx
    数据库的主从复制常用Xshell命令
    Linux搭建主从数据库服务器(主从复制)
    项目数据库备份
    Entity Frameword 查询 sql func linq 对比
    jq 选择器基础及拓展
  • 原文地址:https://www.cnblogs.com/mySummer/p/4614776.html
Copyright © 2011-2022 走看看