2012-12-20 37 views
5

我正在使用Web API將大文件傳輸到客戶端,但我想記錄下載是否成功。也就是說,如果服務器發送了整個文件的內容。當ASP.NET Web API完成發送到客戶端時是否有通知

HttpResponseMessage完成發送數據時,是否有某種方法可以獲得回調或事件?

也許是這樣的:

var stream = GetMyStream(); 
var response = new HttpResponseMessage(HttpStatusCode.OK); 
response.Content = new StreamContent(stream); 
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");  
// This doesn't exist, but it illustrates what I'm trying to do. 
response.OnComplete(context => 
{ 
    if (context.Success) 
     Log.Info("File downloaded successfully."); 
    else 
     Log.Warn("File download was terminated by client."); 
}); 

回答

3

編輯:我現在一直在使用一個真正的連接(通過小提琴手)測試此。

我繼承StreamContent,並加入我自己的OnComplete行動,檢查了異常:

public class StreamContentWithCompletion : StreamContent 
{ 
    public StreamContentWithCompletion(Stream stream) : base (stream) { } 
    public StreamContentWithCompletion(Stream stream, Action<Exception> onComplete) : base(stream) 
    { 
     this.OnComplete = onComplete; 
    } 

    public Action<Exception> OnComplete { get; set; } 

    protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) 
    { 
     var t = base.SerializeToStreamAsync(stream, context); 
     t.ContinueWith(x => 
     { 
      if (this.OnComplete != null) 
      { 
       // The task will be in a faulted state if something went wrong. 
       // I observed the following exception when I aborted the fiddler session: 
       // 'System.Web.HttpException (0x800704CD): The remote host closed the connection.' 
       if (x.IsFaulted) 
        this.OnComplete(x.Exception.GetBaseException()); 
       else 
        this.OnComplete(null); 
      } 
     }, TaskContinuationOptions.ExecuteSynchronously); 
     return t; 
    } 
} 

然後我用它像這樣:

var stream = GetMyStream(); 
var response = new HttpResponseMessage(HttpStatusCode.OK); 
response.Content = new StreamContentWithCompletion(stream, ex => 
{ 
    if (ex == null) 
     Log.Info("File downloaded successfully."); 
    else 
     Log.Warn("File download was terminated by client."); 
}); 
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");  
return response; 
3

我不知道是否有直接的信號,一切都OK,但你可以用一招地發現,你最終它之前的連接存在,並在您完全發送文件後。

例如,Response.IsClientConnected是返回真,如果客戶端仍連接,使您可以檢查類似:

// send the file, make a flush 
Response.Flush(); 
// and now the file is fully sended check if the client is still connected 
if(Response.IsClientConnected) 
{ 
    // log that all looks ok until the last byte. 
} 
else 
{ 
    // the client is not connected, so maybe have lost some data 
} 

// and now close the connection. 
Response.End(); 
+0

我不確定在我使用'ApiController'操作方法時,這對我有用。據我所知,在我返回'HttpResponseMessage'之前什麼也沒有發生。 – ligos

+0

@ligos你可以做一個測試嗎? - 我喜歡說你的另一個,你可以用緩衝區在一個小部分的循環中寫入數據,並檢查最終下載是否與文件大小相同? – Aristos

+0

是的,明天我會進行測試。哦,客戶端無論如何都會有可用的SHA256散列,所以我得到了文件完整性。 – ligos

1

如果服務器發送的全部內容文件

其實沒有興奮:)

這聽起來很簡單,但你會知道是否引發異常 - 如果你關心服務器交付而不是客戶端取消中途。 IsClientConnected基於ASP.NET HttpResponse而不是WebApi。

+0

明天我要去做一些測試,但是你有沒有參考MSDN上拋出的異常呢? – ligos

+0

@ligos取決於什麼地方出了問題。你認爲出了什麼問題?網絡錯誤? – Aliostad

+0

客戶端網絡退出從服務器的角度來看,看起來像是一個連接被丟棄,我會嘗試用提琴模擬這樣的事情 – ligos

相關問題