(原)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,所以不用擔心重複刷新。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章