【发布时间】:2021-09-04 15:24:38
【问题描述】:
我正在尝试使用 Blazor 输入文件以及 Imagesharp 库将 IBrowserFile 转换为图像。
我的方法是这样的
public async Task<byte[]> ConvertFileToByteArrayAsync(IBrowserFile file)
{
using var image = Image.Load(file.OpenReadStream());
image.Mutate(x => x.Resize(new ResizeOptions
{
Mode = ResizeMode.Min,
Size = new Size(128)
}));
MemoryStream memoryStream = new MemoryStream();
if (file.ContentType == "image/png")
{
await image.SaveAsPngAsync(memoryStream);
}
else
{
await image.SaveAsJpegAsync(memoryStream);
}
var byteFile = memoryStream.ToArray();
memoryStream.Close();
memoryStream.Dispose();
return byteFile;
}
但我收到以下错误:
crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: Synchronous reads are not supported.
System.NotSupportedException: Synchronous reads are not supported.
at Microsoft.AspNetCore.Components.Forms.BrowserFileStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.Stream.CopyTo(Stream destination, Int32 bufferSize)
at SixLabors.ImageSharp.Image.WithSeekableStream[ValueTuple`2](Configuration configuration, Stream stream, Func`2 action)
at SixLabors.ImageSharp.Image.Load(Configuration configuration, Stream stream, IImageFormat& format)
at SixLabors.ImageSharp.Image.Load(Configuration configuration, Stream stream)
at SixLabors.ImageSharp.Image.Load(Stream stream)
at MasterMealWA.Client.Services.FileService.ConvertFileToByteArrayAsync(IBrowserFile file) in F:\CoderFoundry\Code\MasterMealWA\MasterMealWA\Client\Services\FileService.cs:line 37
at MasterMealWA.Client.Pages.RecipePages.RecipeCreate.CreateRecipeAsync() in F:\CoderFoundry\Code\MasterMealWA\MasterMealWA\Client\Pages\RecipePages\RecipeCreate.razor:line 128
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.Forms.EditForm.HandleSubmitAsync()
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)
作为记录,第 37 行是“使用 var image ......”,我不太清楚我在哪里使用多个流,除非它是读取流和内存流。但是,我也看不到如何关闭使用 file.OpenReadStream 打开的流。
【问题讨论】:
-
我承认我很惊讶 ImageSharp 完全可以在 Blazor 上工作 - 我猜它使用的是 100% 托管的代码路径,而没有 P/Invoking 到其他图形库?表现如何?您可能在原始 JavaScript 和
<canvas>中执行此操作会更好。 -
无论如何,问题在于 ASP.NET Core(默认情况下)不鼓励人们在 在 ASP.NET Core 自己的流上使用非异步流方法(例如
IBrowserFile.OpenReadStream())。要解决此问题,请改用Image.LoadAsync。 -
所以你下面的修复肯定有效,但你对性能影响也是正确的。它需要 15-30 秒来处理用户端的图像。我想我需要重新考虑一下。
-
正如我所说,要在客户端调整图像大小只需使用
<canvas>- 它在我所知道的所有主要浏览器中都闪电般快速和硬件加速。至于您看到的性能不佳:这正是 Blazor 的工作方式:它在 WASM 中在单个 CPU 线程中执行 CPU 密集型位图操作。尽管 Blazor 的酷炫演示给我留下了深刻的印象,但我并不认为在其中构建生产 Web 应用程序是一个好主意。 -
@HenkHolterman 我接受了它,因为它阐述得很好并解释了我哪里出错了。它只是没有用,因为我一开始就采取了错误的方法。它正确地回答了我的问题,但失败是我的,不是任何人在这里提供建议。
标签: c# asp.net blazor blazor-webassembly imagesharp