ASP.NET中的HTTP協(xié)議
ASP.NET中的HTTP協(xié)議
在Web應(yīng)用程序中處理大文件下載的問題一直出了名的困難,因此對(duì)于大多數(shù)站點(diǎn)來說,如果用戶的下載被中斷了,它們只能說悲哀降臨到用戶的身上了。但是我們現(xiàn)在不必這樣了,因?yàn)槟憧梢允棺约旱腁SP.NET應(yīng)用程序有能力支持可恢復(fù)(繼續(xù))的大文件下載。使用本文提供的方法的時(shí)候,你可以跟蹤下載的過程,這樣你就可以處理動(dòng)態(tài)建立的文件——而且要達(dá)到這個(gè)目標(biāo)根本不需要舊式的ISAPI動(dòng)態(tài)鏈接庫(kù)和非受控的(unmanaged)C++代碼。
為客戶端提供從互聯(lián)網(wǎng)上下載文件的服務(wù)最容易了,對(duì)嗎??jī)H僅只需要把可下載的文件復(fù)制到你的Web應(yīng)用程序目錄中,發(fā)布鏈接并讓IIS完成所有相關(guān)的工作。但是,文件服務(wù)不應(yīng)該比脖子上的疼痛還要多(還要麻煩),你不希望整個(gè)世界都能訪問自己的數(shù)據(jù),你不希望服務(wù)器被數(shù)百個(gè)靜態(tài)文件塞滿了,你甚至于希望下載臨時(shí)文件——只有當(dāng)客戶端開始下載后的空閑時(shí)間才建立這些文件。
不幸的是,使用IIS對(duì)下載請(qǐng)求的默認(rèn)的響應(yīng)是不可能達(dá)到這些效果的。因此在一般情況下,為了獲得對(duì)下載過程的控制權(quán),開發(fā)者需要鏈接到一個(gè)定制的。 aspx頁(yè)面,在這個(gè)頁(yè)面中它們檢查用戶憑證(credential)、建立可以下載的文件并使用下面的代碼把該文件推送給客戶端:
Response.WriteFile
Response.End()
而這就是出現(xiàn)真正麻煩的地方。
有什么問題?
WriteFile方法看起來非常完美,它使文件的二進(jìn)制數(shù)據(jù)流向客戶端。但是直到最近我們才知道,WriteFile方法是一個(gè)出名的內(nèi)存占用狂,它把整個(gè)文件載入服務(wù)器的RAM中來提供服務(wù)(實(shí)際上它甚至于會(huì)占用文件兩倍大小的空間)。對(duì)于大文件,這會(huì)引起服務(wù)內(nèi)存問題,并且可能重復(fù)ASP.NET過程。但是在2004年6月微軟發(fā)布了一個(gè)補(bǔ)丁解決了這個(gè)問題。這個(gè)補(bǔ)丁現(xiàn)在是。NET Framework 1.1補(bǔ)丁包(SP1)的一部分。
這個(gè)補(bǔ)丁引入了TransmitFile方法,它把一個(gè)磁盤文件讀入到較小的內(nèi)存緩沖區(qū)之后就開始傳輸該文件。盡管這個(gè)方案解決了內(nèi)存和循環(huán)的問題,但是它仍然不能令人滿意。你不能控制響應(yīng)的生命周期。你無法知道下載是否正確地完成了,你沒有辦法知道下載是否被中斷了,并且(如果你建立了臨時(shí)文件)你也不知道是否應(yīng)該、以及什么時(shí)候可以刪除這些文件。更糟的是,如果下載的確失敗了,TransmitFile方法又從客戶端下次嘗試的文件頭部開始下載。
其中一種可能的解決方案——實(shí)現(xiàn)后臺(tái)智能傳輸服務(wù)(BITS)對(duì)于多數(shù)站點(diǎn)來說是不可行的,因?yàn)檫@會(huì)毀掉維持客戶端瀏覽器和操作系統(tǒng)獨(dú)立性而作出的努力。
令人滿意的解決方案的基礎(chǔ)還是來自微軟用于解決WriteFile引起的內(nèi)存混亂問題的第一次嘗試(見知識(shí)庫(kù)文章812406)。那篇文章演示了智能的大塊數(shù)據(jù)下載過程,它從文件流中讀取數(shù)據(jù)。在服務(wù)器把字節(jié)塊發(fā)送給客戶端之前,它使用Response.IsClientConnected屬性檢查客戶端是否仍然保持著連接。如果仍然保持連接,它就繼續(xù)發(fā)送流字節(jié),否則就停止,以防止服務(wù)器發(fā)送不必要的數(shù)據(jù)。
這就是我們采用的方法,特別是在下載臨時(shí)文件的時(shí)候。在IsClientConnected返回False的情況下,你就知道下載過程被中斷了,你應(yīng)該保存文件;反之,當(dāng)這個(gè)過程成功完成的時(shí)候,你就刪除臨時(shí)文件。此外,為了恢復(fù)中斷了的下載,你需要做的工作是從上次下載嘗試過程中客戶端連接失敗的文件點(diǎn)開始下載。
HTTP協(xié)議和頭信息(Header)支持
HTTP協(xié)議支持可以用于處理被中斷下載的頭信息。使用少量的HTTP頭信息,你可以增強(qiáng)自己的下載過程,使它完全遵循HTTP協(xié)議規(guī)范。這個(gè)規(guī)范與ranges一起提供恢復(fù)被中斷的下載所需要的一切信息。
【編輯推薦】