2015-06-04 2 views
7

Мне нужно получить длину тела ответа.Как получить текущую длину тела ответа?

Когда я смотрю на https://github.com/aspnet/HttpAbstractions/wiki/Rolling-Notes-Response-Stream-Contract говорится, что:

Stream.Position {получить} и {Stream.Length получить} возвращать кумулятивные записанные байты

Это именно то, что мне нужно, но httpContext.Response.Body.Length поднимает NotSupportedException и говорит: «Поток не доступен для поиска».

Должен ли я использовать поток делегирования для подсчета байтов для каждой записи?

+2

Любопытный, какой сценарий вам нужен? Вероятно, одним из способов получить эту информацию является регистрация для обратного вызова OnSendingHeaders на текущий ответ. Пример: 'httpContext.Response.OnSendingHeaders (callback: (state) => {var length: (HttpContext) state.ContentLength;}, state: httpContext)'. –

+1

Я думаю, что я пропустил вашу последнюю строчку сообщения ... конечно, даже это сработает ... вы могли бы написать промежуточное программное обеспечение, которое зарегистрировано очень рано в конвейере и обертывает тело ответа потоком делегирования ... –

+1

@ KiranChalla Мне требуется длина содержимого для подсчета потребляемой полосы пропускания. Когда квота будет превышена, дальнейшие запросы будут заблокированы/замедлены. Обратный вызов 'OnSendingHeaders' не работает: для свойства' ContentLength' установлено значение 'null'. То же самое происходит с обратным вызовом OnResponseCompleted. – ycrumeyrolle

ответ

2

Я предполагаю, что вы пытаетесь получить ContentLength из промежуточного программного обеспечения?

Приведен пример промежуточного программного обеспечения. Он должен быть добавлен к конвейеру (startup.cs) перед любым промежуточным программным обеспечением, генерирующим ответ, например useMVC или 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); 
     } 
    } 
} 

По причинам, которые находятся за пределами моего понимания при возвращении статических файлов (PNG, JS и т.д.) тело ответа будет пустым, однако ContentLength установлен, поэтому я использовал response.ContentLength ?? buffer.Length.

(примечание к моду: извините за дублированный ответ на два вопроса. Другой ответ был неправильно опубликован, слишком много вкладок открыты. Я удалил его и отправил ответ здесь).

+1

Недостатком этого решения является использование «MemoryStream». Он потребляет бесполезную память. – ycrumeyrolle

+1

Я переопределил «поток» и просто подсчитал при каждом написании следующим образом: public override void Write (byte [] buffer, int offset, int count) { _tracker.ContentLength + = count - offset; _inner.Write (буфер, смещение, счет); } – ycrumeyrolle