ByteArray to IFormFile

Viewed 20035

I am developing some REST API with C# and Net Core
I have a function in my repository which accepts a parameter of type IFormFile.

public async Task<bool> UploadFile(IFormFile file)
{
    // do some stuff and save the file to azure storage
}

This function is called by a controller method which pass it the uploaded file

public class FileController : Controller
{
    public async Task<IActionResult> UploadDoc(IFormFile file
    {
        // Call the repository function to save the file on azure
        var res = await documentRepository.UploadFile(file);
    }
}

Now I have another function that calls an external API which returns a file as a byte array. I'd like to save this byte array using the repository.UploadFile method but I can't cast the byte array object to IFormFile.
Is it possible?

3 Answers

You can convert the byte array to a MemoryStream:

var stream = new MemoryStream(byteArray);

..and then pass that to the constructor of the FromFile class:

IFormFile file = new FormFile(stream, 0, byteArray.Length, "name", "fileName");

Your repo shouldn't be using IFormFile. That's an abstraction that only applies to one particular method of HTTP file transfer (namely a multipart/form-data encoded request body). Something like your repo should have no knowledge of the source of the file (HTTP), nor how it was transmitted (multipart/form-data vs application/json for example).

Instead, you should use Stream for your param. In your UploadDoc action, then, you can simply do:

using (var stream = file.OpenReadStream())
{
    await documentRepository.UploadFile(stream);
}

And, where you have just a byte array:

using (var stream = new MemoryStream(byteArray))
{
    await documentRepository.UploadFile(stream);
}

You might also consider adding an overload of UploadFile that takes a byte[], as creating a new memory stream from a byte array just to have a stream is a waste of resources. However, a byte[] has to be handled differently than a Stream, so it may require some duplication of logic to go that route. You'll need to evaluate the tradeoffs.

  1. Create a new MemoryStream based on the byte array.
  2. Create a new FormFile object based on the MemoryStream.
  3. Make sure to append the ContentDisposition header, otherwise you will be unable to operate your FormFile object as a C# exception will be thrown.

The complete code:

        using (var stream = new MemoryStream(byteArray))
        {
            var file = new FormFile(stream, 0, byteArray.Length, name, fileName)
            {
                Headers = new HeaderDictionary(),
                ContentType = contentType,
            };

            System.Net.Mime.ContentDisposition cd = new System.Net.Mime.ContentDisposition
            {
                FileName = file.FileName
            };
            file.ContentDisposition = cd.ToString();
        }
Related