2

What's wrong with InputFile in Blazor?

(Edit: "what's wrong with my implementation of InputFile, as someone pointed out in the comment")

this was the actual image I'm trying to upload, enter image description here

and this is the resulting display, after uploading; the image is cropped. On top of that, the application also stops working all of a sudden.

enter image description here

and here's the piece of code what is called on the OnChange event of the InputFile

    async Task OnFileChange(InputFileChangeEventArgs e) {
        const string format = "image/png";
        var resizedImage = await e.File.RequestImageFileAsync(format, 512, 512);
        var buffer = new byte[resizedImage.Size];
        await resizedImage.OpenReadStream().ReadAsync(buffer);
        imageBase64 = $"data:{format};base64,{Convert.ToBase64String(buffer)}";
      }

the usual tutorials use 200 or 256 as image size, though all I did was just double the valueenter image description here, which is still below the threshold of the RequestImageFileAsync method which is 512000

Edit 1: this is the snippet of the button that triggers the InputFile

<MudFab HtmlTag="label" Size="Size.Small" Color="Color.Primary" StartIcon="@Icons.Filled.CloudUpload" for="fileInput" />

here's the snippet of the InputFile on the razor page.

<InputFile id="fileInput" OnChange="OnFileChange" hidden multiple accept=".jpg, .jpeg, .png" />

here's the image component displaying the image

<MudImage ObjectFit="ObjectFit.ScaleDown" Src="@imageBase64" Elevation="25"  Class="rounded my-2"></MudImage>

note that I'm indeed using Mudblazor, but I don't think that is of any significance. I tried it on vanilla HTML but still the same issue.

I have slimmed the code so if you put it together, the razor page should look like this:

@page "/tryImage"

<PageTitle>Try Image</PageTitle>

<InputFile id="fileInput" OnChange="OnFileChange" hidden multiple accept=".jpg, .jpeg, .png" />
<MudImage ObjectFit="ObjectFit.ScaleDown" Src="@imageBase64" Elevation="25"  Class="rounded my-2"></MudImage>
<MudFab HtmlTag="label" Size="Size.Small" Color="Color.Primary" StartIcon="@Icons.Filled.CloudUpload" for="fileInput" />


@code {
    private string? imageBase64;
    async Task OnFileChange(InputFileChangeEventArgs e) {
        const string format = "image/png";
        var resizedImage = await e.File.RequestImageFileAsync(format, 512, 512);
        var buffer = new byte[resizedImage.Size];
        await resizedImage.OpenReadStream().ReadAsync(buffer);
        imageBase64 = $"data:{format};base64,{Convert.ToBase64String(buffer)}";
      }
}

Edit 2: Or is it possible that the error has something to do with large images in conflict with RequestImageFileAsync since the sample image I showed above is about 1.2 MB and has dimensions of 4929x3286?

Marlon Dumal-is
  • 300
  • 2
  • 13
  • "What's wrong with InputFile in Blazor? this was the actual image I'm trying to upload" Almost certainly nothing, it's your code. Without more code, your question is impossible to answer. That looks like MudBlazor? – MrC aka Shaun Curtis Jul 19 '22 at 20:14
  • Woah, kinda passive-aggressive comment don't you think? you could have said it nicer. Yes, it's mudblazor, but I don't know if it's relevant, I tried using it without mudblazor and still the same issue. I don't know what kind of code you are looking for, that's the only code that has any relationship with InputFile, but ok, I'll try to add the razor if that's what you're looking for. – Marlon Dumal-is Jul 20 '22 at 06:29
  • @MrCakaShaunCurtis now I have edited the questions please enlighten me with the "Almost certainly, it's your code" comment you made please. thank you very much. – Marlon Dumal-is Jul 20 '22 at 06:45
  • [Polite] No malice intended :-), but many question askers think that the problem is caused by a bug, when in 99+% of the cases it's their code. Your question implied that. Your original question was light on detail and you never mentioned MudBlazor which you were obviously using and may be pertinent to the problem. It's hard for people to help questioners when they don't provide enough detail. – MrC aka Shaun Curtis Jul 20 '22 at 07:57
  • I never intended to say that it was a bug though. I may have expressed my question incorrectly, let me apologize for that, not my 1st language by the way. I skipped mudblazor thinking that it would just cause confusion because like I said, I did use the InputFile the same way without Mudblazor and the cropped image persisted. Nevertheless, I have added my code if it might help. – Marlon Dumal-is Jul 20 '22 at 08:05
  • "On top of that, the application also stops working all of a sudden." Do you have any error/exception in your browser console? Or would this be because you would block Blazor UI with a long task? – T.Trassoudaine Jul 20 '22 at 08:36
  • @T.Trassoudaine, the thing is I did not receive any error when I looked at the Output window of VS. I did not see any error even when I inspect the running application after it stopped working. I could like the buttons but no responses though, It felt like a background task is running so I just let it run for 5 mins, but it never went away, or I should be expecting it to produce errors at the point, but no luck. I just stop working. – Marlon Dumal-is Jul 20 '22 at 08:44
  • @T.Trassoudaine I also did some debugging, and all of the processes finished properly on the OnFileChange method. after the image is loaded on the UI, that is when I get the freezing of the components. I also tried removing all of the other parts of the application leaving just the upload image and I still have the same error. – Marlon Dumal-is Jul 20 '22 at 08:48
  • 1
    Is it Blazor WebAssembly? – T.Trassoudaine Jul 20 '22 at 08:57
  • @T.Trassoudaine I tried on both blazor wasm and server and i got the same result – Marlon Dumal-is Jul 20 '22 at 08:59
  • @T.Trassoudaine my main app was in blazor server, I did retest the application using fewer codes in Blazor wasm (just the image upload process) and the problem seem went away. I don't know why it does not work with blazor server. thanks anyway, I will go for wasm all the way. – Marlon Dumal-is Jul 20 '22 at 12:29
  • I wonder if you are hitting a size limit - either for the `data` url or even for the JS interop between Blazor and the browser - setting an attribute to the base64 encoded image maybe? Try smaller images to see if that is what is happening. You might be better off generating a `dataUrl` blob for the image in JS and using that – Mister Magoo Jul 20 '22 at 15:44
  • @MisterMagoo I also think it's the size that's the issue; reducing the `RequestImageFileAsync` image size produces no error, I haven't tested smaller images, but I guess it will work fine. I think it's the limitation on the JS Interop. let me try what you suggested. But I might stick with Wasm since, there are no issues at all. – Marlon Dumal-is Jul 21 '22 at 01:45
  • This is a duplicated, here is the sam question and solution: https://stackoverflow.com/questions/70790385/ibrowserfile-fromimagefileasync-incomplete-image – MarchalPT Mar 09 '23 at 10:29
  • Does this answer your question? [IBrowserFile FromIMageFileAsync incomplete image](https://stackoverflow.com/questions/70790385/ibrowserfile-fromimagefileasync-incomplete-image) – MarchalPT Mar 09 '23 at 10:30

2 Answers2

3

I faced the same problem on Blazor server side. It wasn't cause by maximum size of the file. No errors, app stuck and only reloading the page helps

I changed this code:

var resized = await browseFile.RequestImageFileAsync(browseFile.ContentType, maxWidth: 500, maxHeight: 800);
var buffer = new byte[resized.Size];
await resized.OpenReadStream(maxAllowedSize: 5120000).ReadAsync(buffer); //500KB
var fileString = $"data:{browseFile.ContentType};base64,{Convert.ToBase64String(buffer)}";

to:

using MemoryStream ms = new();
var resized = await browseFile.RequestImageFileAsync(browseFile.ContentType, maxWidth: 500, maxHeight: 800);
using Stream fileStream = resized.OpenReadStream(); 
await fileStream.CopyToAsync(ms);
                
var fileString = $"data:{browseFile.ContentType};base64,{Convert.ToBase64String(ms.ToArray())}";

and it works :-)
I still don't know where the cause was. If anyone figures it out, let me know

0

This works in this example https://youtu.be/bQ6D4VFMxc4 But it works on net5.0 The problem occurs on net6.0

So I made some changes.

Commented whole program.cs file and copied program.cs and startup.cs from net5.0

In project file I commented

<!--<ImplicitUsings>enable</ImplicitUsings>-->

In Layout.cshtml

Commented

@*<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />*@

and copied form net5.0 host.chtml

<component type="typeof(App)" render-mode="ServerPrerendered" /> 

to body section before @RenderBody.

And it works but this is not solution. If anybody has idea how to make this work in net6.00 or workaround please let me know.

Tito
  • 1
  • 1