Spring MVC项目中通过IE导出报表无法下载

最近一个重构的系统上线后客户发现无法使用IE6下载报表,具体为能弹出“另存为”对话框,但没有显示报表名称,点击保存后报错,无法下载。但是在我的WIN7笔记本上使用IE9和Firefox均能正常下载,使用同事的WIN7下的搜狗浏览器也可以正确下载。由于我将项目的Spring版本从3.0.5.RELEASE升级到了3.1.0.RC1,所以一度以为是由于Spring框架内部的问题,但是在对比的新旧代码后发现问题不在这,新版本的代码中多了一个检测session超时的拦截器,其中有段关键代码:

response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", -1);

 为什么要这样写参见我的这篇博文

先简单说一下我们的报表导出原理,我们采用在Excel上画好模版,另存为“xml模版”,然后将xml的内容复制到jsp文件内,添加jstl支持使jsp文件动态化,用户访问一个url时,control端处理完毕后执行

response.setHeader("Content-Disposition", "attachment; filename=测试报表.xls");

 使用户浏览器弹出一个另存为对话框,保存后就将这个jsp文件变成了后缀名为xls的excel文件(其实本质还是一个文本文件)。

回到导出报表上,通过jmeter工具发送url请求后的取样器结果中包含这样一段:

Thread Name: 线程组 1-1
Sample Start: 2011-10-26 13:38:23 CST
Load time: 5253
Latency: 31
Size in bytes: 12414200
Sample Count: 1
Error Count: 0
Response code: 200
Response message: OK

Response headers:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Expires: Thu, 01-Jan-1970 00:00:00 GMT
Content-Disposition: attachement; filename=excel.xls
Content-Language: zh-CN
Content-Type: application/vnd.ms-excel;charset=gb2312
Set-Cookie: JSESSIONID=e1uhcjpgko27zheg3bfajw6y;Path=/lmkweb
Transfer-Encoding: chunked
Server: Jetty(7.2.0.v20101020)


HTTPSampleResult fields:
ContentType: application/vnd.ms-excel;charset=gb2312
DataEncoding: gb2312

 去掉拦截器的no-cache这段代码后,在IE6中就能正确下载了,所以初步认为是response的header中的Cache-Control和Content-Disposition冲突了(IE6,IE7等等),但是底层细节不甚明了(WIN7的IE9和Firefox没有问题)。

另:在写测试代码时发现一个以前就想知道原因的现象,即如果这个报表文件非常小,IE的另存为对话框弹出后会显示字节数,而如果非常大,等一会儿弹出的对话框不显示字节数,在下载的过程中会显示下载了多少,下载速度等等。

这次在测试的jsp文件中加入了

<% 
for (int i = 0; i < 10000; i++) {
	System.out.println("[" + i + "]");
%>   

...

<% 
}
%>

 在浏览器中测试发现,在控制台打印到70左右时便不再输出了,而页面就弹出另存为对话框,点击保存后,控制台又开始打印。而在jmeter测试中不存在这种暂停。所以初步认为浏览器保存jsp文件时应该有一种缓存机制,非常有意思。

猜你喜欢

转载自stephansun.iteye.com/blog/1216973
今日推荐