2010-01-22 17 views
5

在我工作場所的ASP.net網站上,以下代碼塊負責處理文件下載(注意:此處未使用Response.TransmitFile,因爲下載的內容是從一個zip文件流):下載期間的ASP.net內存使用情況

private void DownloadFile(Stream stream) 
{ 
     int bytesRead; 
     int chunkSize = 1048576; //1MB 

     byte[] readBuffer = new byte[chunkSize]; 
     while ((bytesRead = stream.Read(readBuffer, 0, readBuffer.Length)) != 0) 
      { 
       if(!Response.IsClientConnected) 
        break; 
       byte[] chunk = new byte[bytesRead]; 
       Array.Copy(readBuffer,0,chunk,0,bytesRead); 
       Response.BinaryWrite(chunk); 
       Response.Flush(); 
     } 
     stream.Close(); 
} 

我們的用戶經常下載多百MB的文件,它可以咀嚼服務器內存相當快。我的假設是,這是由於響應緩衝。那有意義嗎?

我剛剛閱讀了關於Response對象的'buffer'屬性。如果我將它設置爲false,是否會阻止Response.BinaryWrite()調用緩衝內存中的數據?一般來說,在這種情況下限制內存使用的好方法是什麼?也許我應該從zip壓縮到臨時文件,然後調用Response.TransmitFile()?

編輯:除了可能的解決方案,我非常感興趣的解釋上面的代碼中存在的內存使用問題。爲什麼這會消耗遠遠超過1MB,即使每次循環迭代都調用Response.Flush?這只是在每次循環迭代時發生的不必要的堆分配(並且不會馬上得到GC),還是還有其他工作?

回答

4

這是我正在爲此工作的一些代碼。它使用一個8000字節的緩衝區以塊形式發送文件。對大文件進行的一些非正式測試顯示分配的內存明顯減少。

int BufferSize = 8000; 
FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read); 
try { 
    long fileSize = stream.Length; 

    long dataLeftToRead = fileSize; 
    int chunkLength; 
    buffer = new Byte[BufferSize]; 

    while (dataLeftToRead > 0) { 
    if (!Response.IsClientConnected) { 
     break; 
    } 
    chunkLength = stream.Read(buffer, 0, BufferSize); 

    Response.OutputStream.Write(buffer, 0, chunkLength); 
    Response.Flush(); 

    dataLeftToRead -= chunkLength; 
    } 
} 
finally { 
    if (stream != null) { 
    stream.Close(); 
} 

編輯,以固定一個語法錯誤和缺失值

+0

夫子評論:8K = 8192個字節; – 2010-01-22 21:33:58

+0

thanx - 修正 - 我們的極客應該嚴謹準確 – Ray 2010-01-22 21:35:45

+2

使用Response.Write與直接寫入Response.OutputStream對象之間有什麼區別? – Odrade 2010-01-22 21:36:31