如何获取当前响应的主体长度? [英] How to retrieve the current response body length?

查看:66
本文介绍了如何获取当前响应的主体长度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要检索响应主体的长度.

I need to retrieve the response body length.

当我查看 https://github.com/aspnet/HttpAbstractions/wiki/Rolling-Notes-Response-Stream-Contract 据说:

Stream.Position {get}和Stream.Length {get}返回写入的累积字节

Stream.Position {get} and Stream.Length {get} return cumulative bytes written

这正是我所需要的,但是 httpContext.Response.Body.Length 引发 NotSupportedException 并说该流不可搜索".

This is exactly what I need, but httpContext.Response.Body.Length raises the NotSupportedException and says "The stream is not seekable."

我应该使用委托流来对每次写入计数字节吗?

Should I use a delegating stream for counting bytes on each write?

推荐答案

以下是用于在流写入过程中跟踪内容长度的代码. ContentLengthTracker 类旨在在其他类之间共享内容长度值.该代码发布在 https://github.com/ycrumeyrolle/Throttling/blob/master/src/Throttling/Internal/ContentLengthTrackingStream.cs

Here is the code for tracking the content length during stream writing. The ContentLengthTracker class is designed for sharing the content length value between other classes. The code is published at https://github.com/ycrumeyrolle/Throttling/blob/master/src/Throttling/Internal/ContentLengthTrackingStream.cs

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

public class ContentLengthTracker
{
    public long ContentLength { get; set; }
}

public class ContentLengthTrackingStream : Stream
{
    private readonly Stream _inner;
    private readonly ContentLengthTracker _tracker;

    public ContentLengthTrackingStream(Stream inner, ContentLengthTracker tracker)
    {
        if (inner == null)
        {
            throw new ArgumentNullException(nameof(inner));
        }

        if (tracker == null)
        {
            throw new ArgumentNullException(nameof(tracker));
        }

        _inner = inner;
        _tracker = tracker;
    }

    public override bool CanRead
        => _inner.CanRead;

    public override bool CanSeek
        => _inner.CanSeek;

    public override bool CanWrite
        => _inner.CanWrite;

    public override long Length
        => _inner.Length;

    public override long Position
    {
        get => _inner.Position;
        set => _inner.Position = value;
    }

    public override bool CanTimeout
        => _inner.CanTimeout;

    public override int ReadTimeout
    {
        get => _inner.ReadTimeout;
        set => _inner.ReadTimeout = value;
    }

    public override int WriteTimeout
    {
        get => _inner.WriteTimeout;
        set => _inner.WriteTimeout = value;
    }

    public ContentLengthTracker Tracker
        => _tracker;

    public override void Flush()
        => _inner.Flush();

    public override Task FlushAsync(CancellationToken cancellationToken)
        => _inner.FlushAsync(cancellationToken);

    public override int Read(byte[] buffer, int offset, int count)
        => _inner.Read(buffer, offset, count);

    public async override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
        => await _inner.ReadAsync(buffer, offset, count, cancellationToken);

    public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
        => _inner.BeginRead(buffer, offset, count, callback, state);

    public override int EndRead(IAsyncResult asyncResult)
    {
        Task<int> task = asyncResult as Task<int>;
        if (task != null)
        {
            return task.GetAwaiter().GetResult();
        }

        return _inner.EndRead(asyncResult);
    }

    public override long Seek(long offset, SeekOrigin origin)
        => _inner.Seek(offset, origin);

    public override void SetLength(long value)
       => _inner.SetLength(value);

    public override void Write(byte[] buffer, int offset, int count)
    {
        _tracker.ContentLength += count - offset;
        _inner.Write(buffer, offset, count);
    }

    public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
    {
        _tracker.ContentLength += count - offset;
        return _inner.BeginWrite(buffer, offset, count, callback, state);
    }

    public override void EndWrite(IAsyncResult asyncResult)
        => _inner.EndWrite(asyncResult);

    public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
    {
        _tracker.ContentLength += count - offset;
        return _inner.WriteAsync(buffer, offset, count, cancellationToken);
    }

    public override void WriteByte(byte value)
    {
        _tracker.ContentLength++;
        _inner.WriteByte(value);
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _inner.Dispose();
        }
    }
}

这篇关于如何获取当前响应的主体长度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆