2013-11-22 45 views
9

在Web API方法我生成一個文件,然後將其分流到像這樣的Web API - 如何檢測時的響應已完成發送

public async Task<HttpResponseMessage> GetFile() { 
    FileInfo file = generateFile(); 
    var msg = Request.CreateResponse(HttpStatusCode.OK); 

    msg.Content = new StreamContent(file.OpenRead()); 
    msg.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf"); 
    msg.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") {FileName = file.Name}; 

    return msg; 
} 

的響應,因爲這是一個生成的文件,我想在響應完成流式處理後將其刪除,但我似乎無法找到管道中的鉤子。

我想我可以把一個靜態文件的引用,並設置一個自定義的MessageHandler,從這個相同的靜態變量拉出值並刪除。然而,這似乎不可能是正確的,因爲使用靜態(當這應該都是每個請求),因爲我必須註冊一個單獨的路線。

我見過this question但它似乎並沒有太多有用的迴應。

回答

10

尼斯場景!...使用消息處理程序的問題是,響應寫發生在主機層和下面的消息處理層,所以它們不是理想......

下面是如何一個例子能做到這一點:

msg.Content = new CustomStreamContent(generatedFilePath); 

public class CustomStreamContent : StreamContent 
{ 
    string filePath; 

    public CustomStreamContent(string filePath) 
     : this(File.OpenRead(filePath)) 
    { 
     this.filePath = filePath; 
    } 

    private CustomStreamContent(Stream fileStream) 
     : base(content: fileStream) 
    { 
    } 

    protected override void Dispose(bool disposing) 
    { 
     //close the file stream 
     base.Dispose(disposing); 

     try 
     { 
      File.Delete(this.filePath); 
     } 
     catch (Exception ex) 
     { 
      //log this exception somewhere so that you know something bad happened 
     } 
    } 
} 

順便說一句,是因爲你把一些數據轉換成PDF您生成此文件。如果是,那麼我認爲你可以使用PushStreamContent來達到這個目的,直接將轉換後的數據寫入響應流。這樣你不需要先生成一個文件,然後再擔心會在以後刪除它。

+0

謝謝基蘭,我試圖用裝飾模式做這樣的事情,並拉我的頭髮,因爲我不能只是重寫公衆。在那個筆記上(並且因爲你在Web Api上工作)任何機會,我們可以讓HttpContent基於未來的接口? –

+0

是的,我正在生成一個pdf,但通過炮轟phantomjs來做到這一點,所以File是我的基本交換格式,不幸的是'Stream' –

0

我們在WebAPI中執行了相同的操作。我需要在下載表單服務器之後立即刪除文件。 我們可以創建自定義響應消息類。它將文件路徑作爲參數,並在傳輸後將其刪除。

public class FileResponseMessage : HttpResponseMessage 
    { 
     private readonly string _filePath; 

     public FileHttpResponseMessage(string filePath) 
     { 
      this._filePath= filePath; 
     } 

     protected override void Dispose(bool disposing) 
     { 
      base.Dispose(disposing); 
      Content.Dispose(); 
      File.Delete(_filePath); 
     } 
    } 

使用此類作爲下面的代碼,它將刪除您的文件,一旦它將被寫入響應流。

var response = new FileResponseMessage(filePath); 
response.StatusCode = HttpStatusCode.OK; 
response.Content = new StreamContent(new FileStream(filePath, FileMode.Open, FileAccess.Read)); 
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") 
{ 
    FileName = "MyReport.pdf" 
}; 
return response; 
+0

您應該只在disposing = true時執行Dispose方法中的代碼。否則,你會遇到問題。 –

相關問題