2014-03-26 35 views
1

回到WebForms時代,我可以使用Response.OutputStream.Write()Response.Flush()將文件數據分塊到客戶端 - 因爲我們流式傳輸的文件很大,並且會消耗太多的Web服務器內存。我現在可以如何使用新的MVC類如FileStreamResult來自數據流的流文件內容

我確切的情況是:DB在VarBinary列中包含文件數據(CSV或XLS)。在WebForms實現中,我發送了一個System.Func到DataAccess層,該層將遍歷IDataReader並使用System.Func將內容流式傳輸到客戶端。關鍵是我不希望Web應用程序必須具有任何特定的數據庫知識,包括IDataReader

如何使用MVC實現相同的結果?

的函數功能是(我在網絡層定義和發送到數據庫層):

Func<byte[], long, bool> partialUpdateFunc = (data, length) => 
    { 
     if (Response.IsClientConnected) 
     { 
      // Write the data to the current output stream. 
      Response.OutputStream.Write(data, 0, (int) length); 

      // Flush the data to the HTML output. 
      Response.Flush(); 

      return true; 
     } 
     else 
     { 
      return false; 
     } 
    }; 

和DB層,我們從DB SP獲得IDataReader(使用的ExecuteReader聲明):

using (var reader = conn.ExecuteReader()) 
{ 
    if (reader.Read()) 
    { 
     byte[] outByte = new byte[BufferSize]; 
     long startIndex = 0; 
     // Read bytes into outByte[] and retain the number of bytes returned. 
     long retval = reader.GetBytes(0, startIndex, outByte, 0, BufferSize); 

     // Continue while there are bytes beyond the size of the buffer. 
     bool stillConnected = true; 
     while (retval == BufferSize) 
     { 
      stillConnected = partialUpdateFunc(outByte, retval); 
      if (!stillConnected) 
      { 
       break; 
      } 

      // Reposition start index to end of last buffer and fill buffer. 
      startIndex += BufferSize; 
      retval = reader.GetBytes(0, startIndex, outByte, 0, BufferSize); 
     } 

     // Write the remaining buffer. 
     if (stillConnected) 
     { 
      partialUpdateFunc(outByte, retval); 
     } 
    } 

    // Close the reader and the connection. 
    reader.Close(); 
} 
+0

對此很好奇...你不希望Web有任何'數據庫引用'...但是,假設你將引用傳遞給響應(在Func中)到DB ... DB層需要參考'Web stuff'?或者因爲數據庫只傳遞一個Func參數,並且沒有公共的'Web參數',所以不需要它? – Terry

回答

1

如果你想重用FileStreamResult您需要創建Stream派生類從數據庫中讀取數據和流傳遞給FileStreamResult

這種做法

  • 行動結果同步執行的,所以當數據從DB /發送讀你的下載也不會釋放線程夫婦的問題 - 可能是確定了少量的並行下載。爲了解決您的問題,您可能需要直接使用處理程序或從異步操作下載(對於MVC方法感覺不對)
  • 至少舊版本的FileStreamResult沒有「流式傳輸」支持(discussed here),請確保您沒有問題。
+0

Thx。我很快考慮創建從IDataReader讀取的自己的Stream派生類。它似乎並不直接,也沒有從谷歌搜索中找到任何示例。任何指針? –

+1

@ Ed.S。不,我沒有樣品。要創建從'Stream'派生並實現'Read'方法的自定義流 - 對於這種情況應該足夠了(將會有其他方法需要,但不需要真正的實現)。好的部分是你可以從'Read'中返回少於字節的字節 - 所以每次詢問時只需從'IDataReader'中讀取一定數量的字節。有關讀取字節的一些示例,請參閱http://stackoverflow.com/questions/891617/how-to-read-a-image-by-idatareader。 –