dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.38k stars 10k forks source link

Kestrel options do not apply. #51763

Closed Hergeirs closed 11 months ago

Hergeirs commented 11 months ago

Is there an existing issue for this?

Describe the bug

I'm using SkiaSharp for a project. They don't have an asynchronous API, so I need to set serverOptions.AllowSynchronousIO = true; in kestrel. For some reason it doesn't seem to have an effect. I'm only setting the option because I'm working with legacy code and can't really change the dependency on SkiaSharp at the moment. As soon as I run SKBitmap.Decode(stream); I get the exeption:

Unhandled exception. System.NotSupportedException: Synchronous reads are not supported.

I have been scouring every resource to try to find a solution.

Expected Behavior

Expect Asynchronous reads to work. After the setting is applied.

Steps To Reproduce

link for minimal git repo

Minimal steps to reproduce from template

@code { private void OnChange(InputFileChangeEventArgs args) { foreach (var file in args.GetMultipleFiles()) { try { var stream = file.OpenReadStream(); var image = SKBitmap.Decode(stream); } catch (Exception) { // Ignore Invalid files } } } }


* Run ``` dotnet run ``` in a terminal.
*  upload a picture.
*  exception is thrown.

### Exceptions (if any)

Unhandled exception. System.NotSupportedException: Synchronous reads are not supported.
   at Microsoft.AspNetCore.Components.Forms.BrowserFileStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at SkiaSharp.SKManagedStream.OnReadManagedStream(IntPtr buffer, IntPtr size)
   at SkiaSharp.SKManagedStream.OnRead(IntPtr buffer, IntPtr size)
   at SkiaSharp.SKAbstractManagedStream.ReadInternal(IntPtr s, Void* context, Void* buffer, IntPtr size)

### .NET Version

7.0.403

### Anything else?

Editor: ```NVIM v0.9.4```

## dotnet --info

.NET SDK: Version: 7.0.403 Commit: 142776d834

Runtime Environment: OS Name: arch OS Version: OS Platform: Linux RID: arch-x64 Base Path: /usr/share/dotnet/sdk/7.0.403/

Host: Version: 7.0.13 Architecture: x64 Commit: 3f73a2f186

.NET SDKs installed: 7.0.403 [/usr/share/dotnet/sdk]

.NET runtimes installed: Microsoft.AspNetCore.App 7.0.13 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App] Microsoft.NETCore.App 7.0.13 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

Other architectures found: None

Environment variables: DOTNET_ROOT [/usr/share/dotnet]

global.json file: Not found

Learn more: https://aka.ms/dotnet/info

Download .NET: https://aka.ms/dotnet/download

BrennanConroy commented 11 months ago

Blazor is throwing that error directly. It has nothing to do with Kestrel. https://github.com/dotnet/aspnetcore/blob/c15938bb5f23fd3ad2374bde554a6b492a36ecde/src/Components/Web/src/Forms/InputFile/BrowserFileStream.cs#L56

Hergeirs commented 11 months ago

I figured. Just tried the only option looking mildly applicable in the docs.

Is there an option to configure Blazor itself to allow it then ? Or at least a workaround without changing the dependency?

SteveSandersonMS commented 11 months ago

The BrowserFileStream can't support synchronous reads because it's reading from a file in the browser's memory, which is only reachable over the network (in the Blazor Server or WebView case).

As a solution in your case, can you asynchronously read the file into memory (as a byte[]) before passing that data to SKBitmap.Decode?

ghost commented 11 months ago

Hi @Hergeirs. We have added the "Needs: Author Feedback" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

Hergeirs commented 11 months ago

Thank you @SteveSandersonMS I should have thought of that. It worked flawlessly.

So basically just changed it (in this example) to:

                using var stream = file.OpenReadStream();
                using var memStream = new MemoryStream();
                await stream.CopyToAsync(memStream);
                var image = SKBitmap.Decode(memStream.ToArray());
SteveSandersonMS commented 11 months ago

Yes that's correct.