'IBrowserFile FromIMageFileAsync incomplete image

I'm uploading images to my app and I'm using this code:

    public static async Task<string> GetThumbnailAndImage(InputFileChangeEventArgs e)
    {
        var file = e.File;

        var imageTmp = await file.RequestImageFileAsync("jpg", 200, 200);

        return image = await UploadMedia(imageTmp);
    }

    public static async Task<string> UploadMedia(IBrowserFile file)
    {
        byte[] bytes = new byte[file.Size];

        var stream = file.OpenReadStream(int.MaxValue);

        await stream.ReadAsync(bytes);

        return Convert.ToBase64String(bytes);
    }

The problem here is, depending on the pixels I ask, the image is partialy uploaded, for example:

enter image description here

I'm expecting the left image but getting the right image.. Does anyone knows what might be causing this problem?

Bests



Solution 1:[1]

@TLP answer solves the problem, but it can still be improved if we follow Microsoft security recommendations to not read files into memory while uploading: https://docs.microsoft.com/en-us/aspnet/core/blazor/file-uploads?view=aspnetcore-6.0&pivots=server

So the correct way to approach this issue is to store the file in a temp file and after converting it to a byte array you close the file stream and delete the tmp file:

    public static async Task<string> UploadMedia(IBrowserFile file)
    {
        var path = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());

        await using var fs = new FileStream(path, FileMode.Create);

        await file.OpenReadStream(file.Size).CopyToAsync(fs);

        var bytes = new byte[file.Size];

        fs.Position = 0;

        await fs.ReadAsync(bytes);            

        fs.Close();

        File.Delete(path);

        return Convert.ToBase64String(bytes);
    }

Solution 2:[2]

It seems that we cannot use the Stream.ReadAsync() method. There is a bug in the framework code for IBrowserFile when using the "MaxAllowedSize" parameter overide. This always writes bytes at the start of the buffer and does not move the postion pointer to the end of the previous buffer write for the next read. This results in only a portion of the image actually being streamed.

My solution is to read the uploaded image file stream, then copy it to a memory stream and convert it to a Byte Array.

Like this:

  public async Task<string> UploadMedia(IBrowserFile file)
  {
    long maxFileSize = 1024 * 1024 * 5; // 5 MB or whatever, don't just use max int
  
    var readStream = file.OpenReadStream(maxFileSize);
  
    var buf = new byte[readStream.Length];
  
    var ms = new MemoryStream(buf);
  
    await readStream.CopyToAsync(ms);
  
    var buffer = ms.ToArray();
  
    return Convert.ToBase64String(buffer);
  }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 MarchalPT
Solution 2