2012-12-20 8 views
5

Używam Web API do strumieniowania dużych plików do klientów, ale chcę się zalogować, jeśli pobieranie się powiodło, czy nie. Oznacza to, że jeśli serwer wysłał całą zawartość pliku.Czy jest powiadomienie, gdy ASP.NET Web API zakończy wysyłanie do klienta

Czy istnieje sposób uzyskania wywołania zwrotnego lub zdarzenia, gdy HttpResponseMessage kończy wysyłanie danych?

Może coś takiego:

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."); 
}); 

Odpowiedz

3

EDIT: Mam już przetestowane przy użyciu prawdziwego połączenia (poprzez Skrzypek).

odziedziczyłem StreamContent i dodaje własne OnComplete działań, które sprawdza, czy wyjątek:

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; 
    } 
} 

Następnie używam go tak:

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

Nie jestem pewien, czy istnieje bezpośredni sygnalizacja, że ​​wszystko jest ok, ale można użyć sztuczki, aby dowiedzieć się, że połączenie jest istnieć tuż przed zakończyć ją , i zaraz po tym, jak w pełni wyślesz plik.

Na przykład Response.IsClientConnected to return true jeśli klient nadal jest podłączony, więc można sprawdzić coś takiego:

// 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

Nie jestem pewien, czy zadziała, gdy będę w metodach działania ApiController. O ile wiem, nic się nie dzieje, dopóki nie zwrócę 'HttpResponseMessage'. – ligos

+0

@ligos Czy możesz zrobić test? - innym, co lubię mówić, czy możesz zapisać swoje dane w pętli małymi partiami z buforem i sprawdzić, czy ostateczne pobranie jest takie samo jak rozmiar pliku? – Aristos

+0

Tak, jutro przeprowadzę test. Aha, i po stronie klienta będzie i tak skrót SHA256 pliku, więc mam integralność plików objętych. – ligos

1

jeśli serwer wysłał całą zawartość plik

W rzeczywistości nie ma Hed to zrobić :)

Może to brzmieć bardzo uproszczona, ale będziesz wiedzieć, czy wyjątek jest podniesiony - jeśli zależy Ci na dostarczaniu serwera, a nie anulowaniu klienta w połowie. IsClientConnected jest oparty na ASP.NET HttpResponse, a nie na WebApi.

+0

Mam zamiar uruchomić kilka testów jutro, ale czy masz odniesienie do wyjątku wyrzuconego na MSDN? – ligos

+0

@ligos zależy od tego, co pójdzie nie tak Co się spodziewać, aby pójść źle? Błąd sieci? – Aliostad

+0

Strona internetowa po stronie klienta wypada Coś, co z punktu widzenia serwera wygląda jak połączenie zerwane, spróbuję zasymulować coś takiego z skrzypkiem – ligos

Powiązane problemy