(原)download后回调刷新页面思路

企业级应用中,经常有要下载***文件的功能。为了减少服务器负担。经常在按下提交按钮的时候,让整张页面处于不可用的状态,以减少重复提交。现在比较流行的做法是用一个大的DIV罩住整个页面。等刷新的时候,DIV因为没有加载,所以页面复原。

这个时候,问题就来了。

看以下代码

response.reset();//可以加也可以不加
response.setContentType("application/x-download");//设置为下载application/x-download


String fileNameDisplay = "***.文件名";
fileNameDisplay = URLEncoder.encode(fileNameDisplay,"UTF-8");
response.addHeader("Content-Disposition","attachment;filename=" + fileNameDisplay);

String fileNameDownload = this.getClass().getClassLoader().getResource("/").getPath() + fileNameDisplay;

OutputStream output = null;
FileInputStream fis = null;
try {
output = response.getOutputStream();
fis = new FileInputStream(fileNameDownload);

byte[] b = new byte[1024];
int i = 0;

while((i = fis.read(b)) > 0)
{
output.write(b, 0, i);
}
output.flush();
}
catch(Exception e)
{
System.out.println("Error!");
e.printStackTrace();
}
finally {
if(fis != null) {
fis.close();
fis = null;
}
if(output != null) {
output.close();
output = null;
}
}

上面的是很典型的download代码

但是在download的过程中,由于强制将文件流写入response,加上调用了out.close();原来的response将不会去刷新页面。

解决方法一:(适用范围IE7+)此方法在IE6下有此属性,但是测试无效
将download Form的target指向一个iframe。(如果是dialog画面,也可以改变base的target)并且加上以下代码


<iframe id="iframe" name="iframe" width="0px" height="0px"></frame>

注意,这里id和name必须都设,这样才能在IE和Firefox下都支持


var iframe = document.getElementById('iframe');
iframe.onreadystatechange = function() {
if (iframe.readyState = "interactive") {
// 这里写还原页面的代码
}
}

readyState有4种状态
[table]
|loading |Object is loading its data. |
|loaded |Object has finished loading its data. |
|interactive |User can interact with the object even though it is not fully loaded.|
|complete |Object is completely initialized. |
[/table]
当执行out.close()的时候,IE7下刚好执行到interactive,但是在IE6下就无效
在其他浏览器下,网上很多人推荐监听iframe的onload句柄。但是一旦out.close,就不触发onload,所以此法无效

方法二(跟浏览器无关)
思路:
企业级应用下载最花时间的是查询和生成文件操作。所以把这些功能和download分开

先在服务器端生成好一个文件。(这段时间页面上显示遮罩DIV)
加上以下代码

// 在session中放入同步令牌
session.setAttribute(DOWNLOAD_TOKEN, 随机数字);


然后不download,直接回来刷新页面
接下来在页面的onload里执行以下代码


<script type="text/javascript">

// 这里的serverFilePath=你服务器上用于download的路径+文件名(需要在web.xml或者(如果是struts,则要在struts-config.xml里配置))
function downloadFile(serverFilePath) {
var iframe = document.getElementById('iframe');
if (iframe) {
iframe.src = serverFilePath;
} else {
window.open(serverFilePath);
}
}
</script>

<body onload="downloadFile('${serverFilePath}')">
<input type="hidden" value="${DOWNLOAD_TOKEN}"/>
</body>


然后在download的那个Servlet里,判断同步令牌里的数字是否一样。
一样则先
session.remove(DOWNLOAD_TOKEN);
然后download
最后删除文件
虽然问题还是有的,但是由于是用看不见的iframe,所以不用担心重复刷新。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章