Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Blazor] HttpPost with StreamContent reads whole file into memory #43388

Closed
1 task done
mrpmorris opened this issue Aug 19, 2022 · 7 comments
Closed
1 task done

[Blazor] HttpPost with StreamContent reads whole file into memory #43388

mrpmorris opened this issue Aug 19, 2022 · 7 comments

Comments

@mrpmorris
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

When using StreamContent with HttpClient.PostAsync in Blazor WASM, the whole file is loaded into memory before initiating the HTTP call

Expected Behavior

The HTTP call should be made immediately, and the data in the stream should be read in chunks.

Steps To Reproduce

1: Create a hosted Blazor WASM app
2: Add the following to WeatherForecast controller

        [HttpPost]
        [RequestFormLimits(MultipartBodyLengthLimit = long.MaxValue)]
        [RequestSizeLimit(long.MaxValue)]
        public IActionResult Upload()
        {
            Console.Beep();
            IFormFile file = Request.Form.Files[0];
            if (file.Length == 0)
                return BadRequest();
            Console.Beep();
            return Ok();
        }

Now try running the following code in both a console app with FileStream as the source for StreamContent, and then inside a Blazor WASM app with IBrowserFile.Open.OpenReadStream as the source

// Console
// using var theSourceStream = new FileStream("c:\\temp\\500MB.zip", FileMode.Open);

// WASM
// var theSourceStream = SomeIBrowserFile.OpenReadStream(long.MaxValue);

var streamContent = new StreamContent(theSourceStream, 4069);
httpContent.Add(streamContent, name: "file", fileName: "somefile.bin");

HttpResponseMessage response = await httpClient.PostAsync("https://localhost:7057/weatherforecast", httpContent);
response.EnsureSuccessStatusCode();

Results

Console app

  1. HttpClient.PostAsync is called
  2. Transfer starts
  3. Server beeps to indicate start of controller code
  4. Data continues to transfer until end (e.g. 10 seconds)
  5. Server beeps to indicate end of controller code
  6. The end

Blazor WASM

  1. HttpClient.PoastAsync is called
  2. Whole file contents are (very slowly) loaded into memory
  3. Transfer starts
  4. Server beeps to indicate start of controller code
  5. Data continues to transfer until end (e.g. 10 seconds)
  6. Server beeps to indicate end of controller code
  7. The end

Exceptions (if any)

No response

.NET Version

6.0.303

Anything else?

WASM

dotnet --info

.NET SDK (reflecting any global.json):
Version: 6.0.303
Commit: 7494fee64a

Runtime Environment:
OS Name: Windows
OS Version: 10.0.19044
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\6.0.303\

global.json file:
Not found

Host:
Version: 6.0.8
Architecture: x64
Commit: 55fb7ef977

.NET SDKs installed:
3.1.422 [C:\Program Files\dotnet\sdk]
6.0.202 [C:\Program Files\dotnet\sdk]
6.0.303 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
Microsoft.AspNetCore.All 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.22 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.28 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.1.22 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.28 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

@campersau
Copy link
Contributor

Related: dotnet/runtime#36634

@javiercn
Copy link
Member

@mrpmorris thanks for contacting us.

Unfortunately, fetch does not support HTTP request body streaming (only supported in Chrome for the time being) so the client needs to buffer. Lets use dotnet/runtime#36634 to track it.

@javiercn javiercn closed this as not planned Won't fix, can't repro, duplicate, stale Aug 19, 2022
@davidfowl
Copy link
Member

Fetch sucks 😢. I've been lobbying the w3c to add this for ages (for different reasons).

@mrpmorris
Copy link
Author

Fetch sucks 😢. I've been lobbying the w3c to add this for ages (for different reasons).

Is there a good reason to use fetch instead of XMLHttpRequest?

@javiercn
Copy link
Member

@mrpmorris you can't stream the request with XMLHttpRequest either. It's not a problem with the API but a missing capability in the browser.

@davidfowl
Copy link
Member

whatwg/fetch#1438

@mrpmorris
Copy link
Author

@javiercn XMLHttpRequest does stream it. I just uploaded a 1GB file without the memory usage going through the roof.

https://twitter.com/MrPeterLMorris/status/1561650669584621568?s=20&t=svki19salJp9qnOvc_So9A

@ghost ghost locked as resolved and limited conversation to collaborators Sep 21, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants