简体   繁体   English

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

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

Problem Statement:问题陈述:

I'm trying to iterate over a Streamed file upload in a HttpPut request using the Request.Body stream and I'm having a real hard time and my google-fu has turned up little.我正在尝试使用 Request.Body stream 在 HttpPut 请求中迭代流式文件上传,但我真的很难过,而且我的 google-fu 几乎没有出现。 The situation is that I expect something like this to work and it doesn't:情况是我希望这样的事情能够奏效,但它不会:

[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);
}

In the debugger, I can examine the Request.Body and look at it's internal _buffer .在调试器中,我可以检查 Request.Body 并查看它的内部_buffer It contains the desired data.它包含所需的数据。 When the above code runs, the MemoryStream is full of zeros.当上面的代码运行时, MemoryStream充满了零。 During "Read", the buffer is also full of zeros.在“读取”期间,缓冲区也充满了零。 The Request.Body also has a length of 0. Request.Body 的长度也为 0。

The Goal:目标:

Use a HttpPut request to upload a file via streaming, iterate over it in chunks, do some processing, and stream those chunks using gRPC to another endpoint.使用 HttpPut 请求通过流式传输上传文件,以块的形式对其进行迭代,进行一些处理,然后 stream 使用 gRPC 将这些块发送到另一个端点。 I want to avoid reading the entire file into memory.我想避免将整个文件读入 memory。

What I've tried:我试过的:

This works:这有效:

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

That code will read all of the Stream into memory as a string which is quite undesirable, but it proves to me that the Request.Body data can be read in some fashion in the method I'm working on.该代码会将所有 Stream 作为字符串读取到 memory 中,这是非常不可取的,但它向我证明,可以在我正在处理的方法中以某种方式读取 Request.Body 数据。

In the configure method of the Startup.cs class, I have included the following to ensure that buffering is enabled:在 Startup.cs class 的配置方法中,我包含以下内容以确保启用缓冲:

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

I have tried encapsulating the Request.Body in another stream like BufferedStream and FileBufferingReadStream and those don't make a difference.我曾尝试将 Request.Body 封装在另一个 stream 中,例如BufferedStreamFileBufferingReadStream ,但这些并没有什么区别。

I've tried:我试过了:

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

This, as well, turns up a MemoryStream with all zeros.这也产生了一个全为零的MemoryStream

I use to do this kind of request body stream a lot in my current project.在我当前的项目中,我经常使用这种请求体 stream 。

This works perfectly fine for me:这对我来说非常好:

[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);
  }
}

The only things I am doing different are:我做的唯一不同的事情是:

  • I am creating the MemoryStream in a scoped context (using).我正在范围上下文中创建MemoryStream (使用)。
  • I am using a slightly bigger buffer (some trial and error led me to this specific size)我正在使用稍大的缓冲区(一些试验和错误使我达到了这个特定的大小)
  • I am using a different overload of Stream.ReadAsync , where I pass the bytes[] buffer, the reading length and the reading start position as 0.我正在使用Stream.ReadAsync的不同重载,其中我将bytes[]缓冲区、读取长度和读取开始 position 传递为 0。

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

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