在ASP.NET中跟蹤和恢複大檔案下載
來源:互聯網
上載者:User
在Web應用程式中處理大檔案下載的問題一直出了名的困難,因此對於大多數網站來說,如果使用者的下載被中斷了,它們只能說悲哀降臨到使用者的身上了。但是我們現在不必這樣了,因為你可以使自己的ASP.NET應用程式有能力支援可恢複(繼續)的大檔案下載。使用本文提供的方法的時候,你可以跟蹤下載的過程,這樣你就可以處理動態建立的檔案--而且要達到這個目標根本不需要舊式的ISAPI動態連結程式庫和非受控的(unmanaged)C++代碼。
為用戶端提供從互連網上下載檔案的服務最容易了,對嗎?僅僅只需要把可下載的檔案複製到你的Web應用程式目錄中,發布連結並讓IIS完成所有相關的工作。但是,檔案服務不應該比脖子上的疼痛還要多(還要麻煩),你不希望整個世界都能訪問自己的資料,你不希望伺服器被數百個靜態檔案塞滿了,你甚至於希望下載臨時檔案--只有當用戶端開始下載後的空閑時間才建立這些檔案。
不幸的是,使用IIS對下載請求的預設的響應是不可能達到這些效果的。因此在一般情況下,為了獲得對下載過程的控制權,開發人員需要連結到一個定製的.aspx頁面,在這個頁面中它們檢查使用者憑證(credential)、建立可以下載的檔案並使用下面的代碼把該檔案推送給用戶端:
Response.WriteFile
Response.End()
而這就是出現真正麻煩的地方。
有什麼問題?
WriteFile方法看起來非常完美,它使檔案的位元據流向用戶端。但是直到最近我們才知道,WriteFile方法是一個出名的記憶體佔用狂,它把整個檔案載入伺服器的RAM中來提供服務(實際上它甚至於會佔用檔案兩倍大小的空間)。對於大檔案,這會引起服務記憶體問題,並且可能重複ASP.NET過程。但是在2004年6月微軟發布了一個補丁解決了這個問題。這個補丁現在是.NET Framework 1.1補丁包(SP1)的一部分。
這個補丁引入了TransmitFile方法,它把一個磁碟檔案讀入到較小的記憶體緩衝區之後就開始傳輸該檔案。儘管這個方案解決了記憶體和迴圈的問題,但是它仍然不能令人滿意。你不能控制響應的生命週期。你無法知道下載是否正確地完成了,你沒有辦法知道下載是否被中斷了,並且(如果你建立了臨時檔案)你也不知道是否應該、以及什麼時候可以刪除這些檔案。更糟的是,如果下載的確失敗了,TransmitFile方法又從用戶端下次嘗試的檔案頭部開始下載。