You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# ASP.NET Web API如何从服务器端监控流传输进度?

监控ASP.NET Web API流传输进度的简便方案

方案1:装饰器模式包装流(推荐)

不用完全继承实现Stream的所有抽象方法,只需创建一个包装流,仅重写Read方法处理进度,其余方法直接委托给原始流即可,大幅减少代码量:

public class ProgressStream : Stream
{
    private readonly Stream _baseStream;
    private readonly Action<long> _progressCallback;
    private long _bytesRead;

    public ProgressStream(Stream baseStream, Action<long> progressCallback)
    {
        _baseStream = baseStream ?? throw new ArgumentNullException(nameof(baseStream));
        _progressCallback = progressCallback ?? throw new ArgumentNullException(nameof(progressCallback));
    }

    // 仅重写Read方法监控进度
    public override int Read(byte[] buffer, int offset, int count)
    {
        int bytesRead = _baseStream.Read(buffer, offset, count);
        if (bytesRead > 0)
        {
            _bytesRead += bytesRead;
            _progressCallback(_bytesRead);
        }
        return bytesRead;
    }

    // 其余方法直接复用原始流逻辑,无需自行实现
    public override bool CanRead => _baseStream.CanRead;
    public override bool CanSeek => _baseStream.CanSeek;
    public override bool CanWrite => _baseStream.CanWrite;
    public override long Length => _baseStream.Length;
    public override long Position 
    { 
        get => _baseStream.Position; 
        set => _baseStream.Position = value; 
    }
    public override void Flush() => _baseStream.Flush();
    public override long Seek(long offset, SeekOrigin origin) => _baseStream.Seek(offset, origin);
    public override void SetLength(long value) => _baseStream.SetLength(value);
    public override void Write(byte[] buffer, int offset, int count) => _baseStream.Write(buffer, offset, count);
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _baseStream.Dispose();
        }
        base.Dispose(disposing);
    }
}

使用示例

结合你现有代码,只需将原始FileStream包装为ProgressStream,传入进度处理逻辑:

var filePath = @"c:\largefile.tmp";
using var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);

// 包装流并传入进度回调(比如记录日志、统计传输量)
using var progressStream = new ProgressStream(fs, bytesRead =>
{
    var totalBytes = fs.Length;
    var progressPercent = (double)bytesRead / totalBytes * 100;
    Console.WriteLine($"已传输 {bytesRead}/{totalBytes} 字节,进度:{progressPercent:F2}%");
});

var result = new HttpResponseMessage(HttpStatusCode.OK)
{
    Content = new StreamContent(progressStream, 8192)
};

方案2:自定义HttpContent

若不想包装流,也可直接扩展HttpContent,重写SerializeToStreamAsync方法监控传输进度:

public class ProgressStreamContent : StreamContent
{
    private readonly long _totalBytes;
    private readonly Action<long> _progressCallback;
    private long _bytesWritten;

    public ProgressStreamContent(Stream stream, int bufferSize, long totalBytes, Action<long> progressCallback) 
        : base(stream, bufferSize)
    {
        _totalBytes = totalBytes;
        _progressCallback = progressCallback;
    }

    protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context)
    {
        var buffer = new byte[this.BufferSize];
        int bytesRead;
        while ((bytesRead = await this.Content.ReadAsync(buffer, 0, buffer.Length)) > 0)
        {
            await stream.WriteAsync(buffer, 0, bytesRead);
            _bytesWritten += bytesRead;
            _progressCallback(_bytesWritten);
        }
    }
}

使用示例

var filePath = @"c:\largefile.tmp";
using var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
var totalBytes = fs.Length;

var result = new HttpResponseMessage(HttpStatusCode.OK)
{
    Content = new ProgressStreamContent(fs, 8192, totalBytes, bytesWritten =>
    {
        var progressPercent = (double)bytesWritten / totalBytes * 100;
        Console.WriteLine($"已传输 {bytesWritten}/{totalBytes} 字节,进度:{progressPercent:F2}%");
    })
};

方案优势

  • 装饰器流仅需实现核心的进度监控逻辑,其余方法复用原始流能力,避免了完全实现Stream抽象类的冗余工作;
  • 自定义HttpContent贴合Web API响应场景,无需额外流包装,逻辑更聚焦。

内容的提问来源于stack exchange,提问作者Edison C

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 09:46:13