注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

一线天色 天宇星辰

天下武功,唯快不破

 
 
 

日志

 
 

https下无法下载附件的解决方案  

2011-04-14 22:19:10|  分类: 软件开发 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

最近做一个提供下载Excel数据的模块,用的是基于Struts2的流传输,模块做完之后,在研发环境下测试通过,交与质保部门测试的过程中发现文件始终不能下载!远程调试,也没发生什么错误,就是无法下载!如下图所示!https下无法下载附件的解决方案 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 

Struts2的配置对应为

           <result name="success" type="stream">

              <param name="contentType">application/vnd.ms-excel</param>

              <param name="inputName">inputStream</param>

              <param name="contentDisposition">attachment;filename="${fileName}"</param>

              <param name="bufferSize">4096</param><!-- 输出时缓冲区的大小 -->

           </result>

和研发对比环境,发现质保部门是在https的协议下运行的。

我再次确认,发现在http协议下整个功能是ok的,但是IE的环境下在https下的确不能下载!Firfoxchrome是可以的,这是为什么呢?

网上搜索,说是因为我没有告知浏览器body响应体的大小,需要设置Content-Length这个属性,于是我重新修改代码,去取生成的Excel文件的字节码的大小,然后防止到requestheader里面。重新部署,发布。点击我要生成Excel的按钮,奇迹出现了,浏览器的迅雷插件检测到了这个下载流,拦截了对应的下载流并启动了下载界面,点击下载,果然下载成功了!我欣喜的通知测试再次验证,发现测试部门依旧不能下载,提上上面的界面!

这是为什么呢?于是乎我重新开启了远程调试,终于,我发现了迅雷能够下载的原因:原来迅雷的插件每次去监控浏览器的header信息,发现非空字节流和文件流就会去下载,然后结束浏览器自己的下载线程,而前面未填写headerbody大小,因此迅雷的插件没有捕获这一字节流,而填写了body的长度后,迅雷捕获了这一字节流,然后结束当前浏览器自己的下载字节流,但是迅雷只记载下载的路径,因此它会重新请求一次下载的地址,去下载文件,整个远程调试过程中生成文件并输出到页面被调了2次。而在没有安装下载工具的pc上面,还是原来的问题,无法下载对应的文件!

继续搜索,有人说是因为返回的头中cache-control是私有的,而ssl不允许采用no-cache方式进行下载,必须采用public方式下载才能够正常。于是我用Fiddler去抓取对应的数据,如下所示

https下无法下载附件的解决方案 - 一线天色 天宇星辰 - 一线天色 天宇星辰
 

对应的Pragma(和cache-control表达的是一个意思)的值是no-cache,即不缓存,所以在基于SSL安全的协议(https)下,IE默认不允许用户下载该文件!问题找到了,我们就好解决了,怎么做呢?将对应的Pragmacache-control)设置为public不就可以了吗?于是修改代码,加入如下代码:

       ExcelPageWriter pageWriter= ExcelUtil.writeExcel(list, colList);

//     getResponse().setHeader("Content-Length",String.valueOf(pageWriter.getSize()));

       getResponse().setHeader("cache-control","public");

       getResponse().setHeader("Pragma","public");

       return pageWriter.getInputStream();

测试,ok,完全通过!

但是这样还不太好,一般我们在Struts2里面是不通过直接操作responseheader的,于是修改代码,将对应的数据写在配置的xml中,如下所示:

    <result name="success" type="stream">

              <param name="contentType">application/vnd.ms-excel</param>

              <param name="cache-control">application/vnd.ms-excel</param>

              <param name="Pragma">public</param>

              <param name="inputName">public</param>

              <param name="contentDisposition">attachment;filename="${fileName}"</param>

              <param name="bufferSize">4096</param><!-- 输出时缓冲区的大小 -->

           </result>

再次测试,ok,通过,问题终于解决了!

 你觉得本文对你帮助吗?  

票数:26 投票时间:2011-04-14 22:19:10 到 2014-12-31 23:00:00

  •     24(92.3%)
  •     0(0%)
  •     1(3.8%)
  •     0(0%)
  •     1(3.8%)
查看参与情况
编辑投票|删除投票

最新投票|博友投票

      评论这张
     
    阅读(64799)| 评论(0)
    推荐 转载

    历史上的今天

    评论

    <#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
     
     
     
     
     
     
     
     
     
     
     
     
     
     

    页脚

    网易公司版权所有 ©1997-2017