2016-02-11 42 views
6

我已經創建了一個基於MVC 5的WebAPI控制器 - 它爲我們的客戶提供了不同的文件。訪問這些文件的工具也是自行編寫的 - 基於.NET HttpClient - 但那是另一個故事。MVC 5 WebAPI - 下載文件 - HttpException

在下載控制器的第一個版本,我使用的生成機制來提供文件,如this

但該機制墜毀在我的IIS的文件> 4GB。

於是,我終於來到了這個代碼:

public class DownloadController : ApiController 
    { 
     public async Task Get(long id) 
     { 
      string fullFilePath = GetFilePathById(id); 
      string returnFileName = fullFilePath.Split('\\').Last(); 
      FileInfo path = new FileInfo(fullFilePath); 
      HttpContext.Current.Response.ContentType = "application/zip"; 
      HttpContext.Current.Response.AddHeader("Content-Length", path.Length.ToString()); 
      HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + returnFileName); 
      HttpContext.Current.Response.Flush(); 
     try 
     { 
      byte[] buffer = new byte[4096]; 
      using (FileStream fs = path.OpenRead()) 
      { 
       using (BufferedStream bs = new BufferedStream(fs, 524288)) 
       { 
        int count = 0; 
        while ((count = bs.Read(buffer, 0, buffer.Length)) > 0) 
        { 
         if (!HttpContext.Current.Response.IsClientConnected) 
         { 
          break; 
         } 
         HttpContext.Current.Response.OutputStream.Write(buffer, 0, count); 
         HttpContext.Current.Response.Flush(); 
        } 
       } 
      } 
     } 
     catch (Exception exception) 
     { 
      //Exception logging here 
     } 
    } 
} 

該代碼工作得很好,我得到了快速的下載與可接受的CPU使用率和磁盤I/O。但一段時間後,我發現 - 與每一個下載 - 未處理的異常,這樣寫一個進入應用程序事件日誌IIS服務器的:

Server cannot set status after HTTP headers have been sent 

Exception type: HttpException 

Event Log ID 1309 

我敢肯定,重複使用.Flush的()導致問題,但如果我刪除了這些下載停止工作。

在類似的問題,我可以找到Response.BufferOutput = true;作爲解決方案,但似乎吃掉我所有的服務器資源,並延遲下載。

任何建議將是偉大的!

+1

您是否嘗試在最後添加一個'HttpContext.Current.Response.Close()'?或者,如果適用(並且不需要進一步處理),'HttpContext.Current.ApplicationInstance.CompleteRequest()'? – Jcl

+0

你沒有使用StreamContent的原因是什麼? – martennis

+0

@Jcl我會嘗試一下,並給你一個反饋。 – maltmann

回答

1

的問題是不是與Flush(),但你不與HttpContext.Current.Response.Close();

關閉響應流自己的ASP.NET框架不知道你的操作方法裏面做什麼,所以它傳遞請求通過通常的請求管道,而不是我們做所有必要的管道。其中之一是它將頭和HTTP狀態發送到客戶端。但是,當框架嘗試這樣做時,您已經設置併發送了標頭。爲了避免這種情況,您應該關閉流,並通過關閉響應流來完成處理。

+0

.Close()並未解決此問題。有一個想法,我可以如何防止發送HTTP頭? – maltmann

+0

你能否在Fiddler中檢查正在發送的標題? – Tamas

+0

標題只有一次到達。我傾向於全局抑制此異常以保持服務器事件日誌的清潔 – maltmann