繁体   English   中英

ASP.NET Core 3.1读取stream文件上传在HttpPut请求问题

[英]ASP.NET Core 3.1 read stream file upload in HttpPut request problem

问题陈述:

我正在尝试使用 Request.Body stream 在 HttpPut 请求中迭代流式文件上传,但我真的很难过,而且我的 google-fu 几乎没有出现。 情况是我希望这样的事情能够奏效,但它不会:

[HttpPut("{accountName}/{subAccount}/{revisionId}/{randomNumber}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> PutTest()
{
    var memStream = new MemoryStream();
    var b = new Memory<byte>();
    int totalBytes = 0;
    int bytesRead = 0;
    byte[] buffer = new byte[1024];

    do
    {
        bytesRead = await Request.Body.ReadAsync(new Memory<byte>(buffer), CancellationToken.None);
        totalBytes += bytesRead;
        await memStream.WriteAsync(buffer, 0, bytesRead);
    } while (bytesRead > 0);
    
    return Ok(memStream);
}

在调试器中,我可以检查 Request.Body 并查看它的内部_buffer 它包含所需的数据。 当上面的代码运行时, MemoryStream充满了零。 在“读取”期间,缓冲区也充满了零。 Request.Body 的长度也为 0。

目标:

使用 HttpPut 请求通过流式传输上传文件,以块的形式对其进行迭代,进行一些处理,然后 stream 使用 gRPC 将这些块发送到另一个端点。 我想避免将整个文件读入 memory。

我试过的:

这有效:

using (var sr = new StreamReader(Request.Body))
{
    var body = await sr.ReadToEndAsync();
    return Ok(body);
}

该代码会将所有 Stream 作为字符串读取到 memory 中,这是非常不可取的,但它向我证明,可以在我正在处理的方法中以某种方式读取 Request.Body 数据。

在 Startup.cs class 的配置方法中,我包含以下内容以确保启用缓冲:

app.Use(async (context, next) => {
                context.Request.EnableBuffering();
                await next();
            });

我曾尝试将 Request.Body 封装在另一个 stream 中,例如BufferedStreamFileBufferingReadStream ,但这些并没有什么区别。

我试过了:

var reader = new BinaryReader(Request.Body, Encoding.Default);
do
{
    bytesRead = reader.Read(buffer, 0, buffer.Length);
    await memStream.WriteAsync(buffer);
} while (bytesRead > 0);

这也产生了一个全为零的MemoryStream

在我当前的项目中,我经常使用这种请求体 stream 。

这对我来说非常好:

[HttpPut("{accountName}/{subAccount}/{revisionId}/{randomNumber}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> PutTest(CancellationToken cancel) {
  using (var to = new MemoryStream()) {
    var from = HttpContext.Request.Body;
    var buffer = new byte[8 * 1024];
    long totalBytes = 0;
    int bytesRead;
    while ((bytesRead = await from.ReadAsync(buffer, 0, buffer.Length, cancel)) > 0) {
      await to.WriteAsync(buffer, 0, bytesRead, cancel);
      totalBytes += bytesRead;
    }
    return Ok(to);
  }
}

我做的唯一不同的事情是:

  • 我正在范围上下文中创建MemoryStream (使用)。
  • 我正在使用稍大的缓冲区(一些试验和错误使我达到了这个特定的大小)
  • 我正在使用Stream.ReadAsync的不同重载,其中我将bytes[]缓冲区、读取长度和读取开始 position 传递为 0。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM