2015-06-04 8 views
7

Potrzebuję pobrać długość odpowiedzi.Jak odzyskać bieżącą długość ciała odpowiedzi?

Kiedy patrzę na https://github.com/aspnet/HttpAbstractions/wiki/Rolling-Notes-Response-Stream-Contract jest powiedziane, że:

Stream.Position {get {} i Stream.Length dostać} powrót skumulowane bajtów zapisanych

To jest dokładnie to, czego potrzebuję, ale httpContext.Response.Body.Length podnosi NotSupportedException i mówi "Strumień nie jest widoczny".

Czy powinienem użyć strumienia delegującego do liczenia bajtów przy każdym zapisie?

+2

Ciekawy, jaki jest scenariusz, w którym jest to potrzebne? Prawdopodobnie jednym ze sposobów uzyskania tych informacji jest zarejestrowanie się w wywołaniu zwrotnym 'OnSendingHeaders' w bieżącej odpowiedzi. Przykład: 'httpContext.Response.OnSendingHeaders (callback: (stan) => {var length: (HttpContext) state.ContentLength;}, state: httpContext)'. –

+1

Myślę, że przegapiłem twoją ostatnią linię postu ... na pewno, nawet to by działało ... możesz napisać oprogramowanie pośredniczące, które jest rejestrowane bardzo wcześnie w potoku i owija ciało odpowiedzi strumieniem delegującym ... –

+1

@ KiranChalla Wymagam długości zawartości do zliczania zużytej przepustowości. Kiedy limit zostanie przekroczony, dalsze żądania będą blokowane/spowalniane. Wywołanie zwrotne 'OnSendingHeaders' nie działa: Właściwość' ContentLength' ma wartość 'null'. To samo dotyczy wywołania zwrotnego 'OnResponseCompleted'. – ycrumeyrolle

Odpowiedz

2

Zakładam, że próbujesz pobrać ContentLength z oprogramowania pośredniego?

Oto przykład Middleware. Powinien zostać dodany do potoku (startup.cs) przed dowolnym oprogramowaniem pośredniczącym generującym odpowiedzi, takim jak useMVC lub useStaticFiles.

public class ContentLengthMiddleware 
{ 
    RequestDelegate _next; 

    public ContentLengthMiddleware(RequestDelegate next) 
    { 
     _next = next; 
    } 

    public async Task Invoke(HttpContext context) 
    { 
     using (var buffer = new MemoryStream()) 
     { 
      var request = context.Request; 
      var response = context.Response; 

      var bodyStream = response.Body; 
      response.Body = buffer; 

      await _next(context); 
      Debug.WriteLine($"{request.Path} ({response.ContentType}) Content-Length: {response.ContentLength ?? buffer.Length}"); 
      buffer.Position = 0; 
      await buffer.CopyToAsync(bodyStream); 
     } 
    } 
} 

Z powodów, które są poza moim zrozumieniem po powrocie statycznych plików (PNG, JS, etc) ciało odpowiedź będzie pusta jednak ContentLength jest ustawiony dlatego użyłem response.ContentLength ?? buffer.Length.

(Uwaga na mod: przepraszam za duplikat odpowiedzi na dwa pytania, druga odpowiedź została niepoprawnie opublikowana, zbyt wiele zakładek otwartych, usunąłem ją i przeredagowałem odpowiedź tutaj).

+1

Wadą tego rozwiązania jest użycie 'MemoryStream'. Zużywa niepotrzebnie pamięci. – ycrumeyrolle

+1

Nadpisałem 'Stream' i po prostu liczyć przy każdym zapisie w ten sposób: public override void Write (bufor byte [], int offset, int count) { _tracker.ContentLength + = count - offset; _inner.Write (bufor, przesunięcie, liczba); } – ycrumeyrolle

Powiązane problemy