Search code examples
asp.net-coreasynchronousfilestreammemorystreamimagesharp

.NET Core API saving image upload asynchronously with ImageSharp, MemoryStream and FileStream


I have a .NET Core API that I'd like to extend to save uploaded images asynchronously.

Using ImageSharp I should be able to check uploads and resize if predefined size limits are exceeded. However I can't get a simple async save working.

A simple (non-async) save to file works without problem:

My Controller extracts IFormFile from the upload and calls the following method without any problem

public static void Save(IFormFile image, string imagesFolder)
{
    var fileName = Path.Combine(imagesFolder, image.FileName);

    using (var stream = image.OpenReadStream())
    using (var imgIS = Image.Load(stream, out IImageFormat format))
    {
        imgIS.Save(fileName);
    }
}

ImageSharp is currently lacking async methods so a workaround is necessary.

The updated code below saves the uploaded file but the format is incorrect - when viewing the file I get the message "It appears we don't support this file format".

The format is extracted from the ImageSharp Load method. and used when saving to MemoryStream.

MemoryStream CopyToAsync method is used to save to FileStream to make the upload asynchronous.

public static async void Save(IFormFile image, string imagesFolder)
{
    var fileName = Path.Combine(imagesFolder, image.FileName);

    using (var stream = image.OpenReadStream())
    using (var imgIS = Image.Load(stream, out IImageFormat format))
    using (var memoryStream = new MemoryStream())
    using (var fileStream = new FileStream(fileName, FileMode.OpenOrCreate))
    {      
        imgIS.Save(memoryStream, format);

        await memoryStream.CopyToAsync(fileStream).ConfigureAwait(false);
        fileStream.Flush();
        memoryStream.Close();
        fileStream.Close();
    }
}

I can't work out whether the issue is with ImageSharp Save to MemoryStream, or the MemoryStream.CopyToAsync.

I'm currently getting 404 on SixLabors docs - hopefully not an indication that the project has folded.

How can I make the upload async and save to file in the correct format?


Solution

  • CopyToAsync copies a stream starting at its current position. You must change the current position of memoryStream back to start before copying:

        // ...
        memoryStream.Seek(0, SeekOrigin.Begin);
        await memoryStream.CopyToAsync(fileStream).ConfigureAwait(false);
       // ...