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-1Sample Start: 2011-10-26 13:38:23 CSTLoad time: 5253Latency: 31Size in bytes: 12414200Sample Count: 1Error Count: 0Response code: 200Response message: OKResponse headers:HTTP/1.1 200 OKCache-Control: no-cachePragma: no-cacheExpires: Thu, 01-Jan-1970 00:00:00 GMTContent-Disposition: attachement; filename=excel.xlsContent-Language: zh-CNContent-Type: application/vnd.ms-excel;charset=gb2312Set-Cookie: JSESSIONID=e1uhcjpgko27zheg3bfajw6y;Path=/lmkwebTransfer-Encoding: chunkedServer: Jetty(7.2.0.v20101020)HTTPSampleResult fields:ContentType: application/vnd.ms-excel;charset=gb2312DataEncoding: 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文件时应该有一种缓存机制,非常有意思。
?