मैं एक IBrowserFile को एक छवि में बदलने के लिए, एक Blazor इनपुट फ़ाइल और इमेजशार्प लाइब्रेरी का उपयोग करने का प्रयास कर रहा हूँ।
मेरी विधि इस तरह दिखती है

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 का उपयोग कर रहा है ......" है, मैं यह नहीं देखता कि मैं एकाधिक स्ट्रीम का उपयोग कहां कर रहा हूं, जब तक कि यह पढ़ने वाली स्ट्रीम और मेमोरी स्ट्रीम न हो। हालांकि, मैं यह भी नहीं देखता कि फ़ाइल के साथ खुलने वाली स्ट्रीम को कैसे बंद किया जाए। OpenReadStream।

0
sbrevolution5 4 सितंबर 2021, 18:24

3 जवाब

सबसे बढ़िया उत्तर

पृष्ठभूमि:

उचित समाधान:

आप ImageSharp की Image.Load विधि को कॉल कर रहे हैं, जो गैर-async Stream विधियों का उपयोग करती है। इसके बजाय केवल await Image.LoadAsync का उपयोग करना ठीक है:

तो अपना कोड इसमें बदलें:

// I assume this is a Controller Action method
// This method does not return an IActionResult because it writes directly to the response in the action method. See examples here: https://stackoverflow.com/questions/42771409/how-to-stream-with-asp-net-core

public async Task ResizeImageAsync( IBrowserFile file )
{
    await using( Stream stream = file.OpenReadStream() )
    using( Image image = await Image.LoadAsync( stream ) )
    {
        ResizeOptions ro = new ResizeOptions
        {
            Mode = ResizeMode.Min,
            Size = new Size(128)
        };

        image.Mutate( img => img.Resize( ro ) );

        if( file.ContentType == "image/png" ) // <-- You should not do this: *never trust* the client to be correct and truthful about uploaded files' types and contents. In this case it's just images so it's not that big a deal, but always verify independently server-side.
        {
            this.Response.ContentType = "image/png";
            await image.SaveAsPngAsync( this.Response.Body );
        }
        else
        {
            this.Response.ContentType = "image/jpeg";
            await image.SaveAsJpegAsync( this.Response.Body );
        }
}

वैकल्पिक (गैर-) समाधान: विलंबित:

गैर-async IO पर बस ASP.NET कोर के निषेध को अक्षम करें:

public void ConfigureServices(IServiceCollection services)
{
    // If using Kestrel:
    services.Configure<KestrelServerOptions>(options =>
    {
        options.AllowSynchronousIO = true;
    });

    // If using IIS:
    services.Configure<IISServerOptions>(options =>
    {
        options.AllowSynchronousIO = true;
    });
}
2
Dai 4 सितंबर 2021, 17:07

Image.Load एक सिंक्रोनाइज्ड ऑपरेशन है। इसके बजाय async संस्करण के साथ प्रयास करें:

using var image = await Image.LoadAsync(file.OpenReadStream());
1
PEK 4 सितंबर 2021, 17:03

आपको सिंक्रोनस Dispose() के बजाय LoadAsync, DisposeAsync() जैसी async विधियों को कॉल करना होगा। DisposeAsync() पर कॉल की प्रतीक्षा करने के लिए await using xxx का उपयोग करें।

public async Task<byte[]> ConvertFileToByteArrayAsync(IBrowserFile file)
{
    await using var image = await image.LoadAsync(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();
    await memoryStream.DisposeAsync();

    return byteFile;
}
1
Peter Bons 4 सितंबर 2021, 17:35