Como converter Object para MultipartFormDataContent ASP.NET

raiitto

Railson Ferreira de Souza

Posted on February 19, 2021

Como converter Object para MultipartFormDataContent ASP.NET

Quando queremos enviar um objeto com os parâmetros necessários para um requisição Post em uma API basta usar o método HttpClientJsonExtensions.PostAsJsonAsync(), mas as coisas mudam um pouco quando queremos enviar também arquivos nesta requisição, pois o formato json não suporta um parâmetro de arquivo.

A forma mais comum para enviar formulários que contém arquivos, para uma API, é utilizando multipart/form-data, que é suportado pelo protocolo http.

No ASP.NET não temos algo como PostAsMultipartFormDataAsync(). Eu utilizo o seguinte código para converter objetos, com parâmetros e arquivos, para um MultiPartFormDataContent, para então enviá-lo à API.

public class MultipartFormDataContentParser<T>
{
    private T _obj;
    public MultipartFormDataContentParser(T obj)
    {
        _obj = obj;
    }
    public MultipartFormDataContent Parse()
    {
        var formContent = new MultipartFormDataContent();
        var genericFileName = "Filename";

        var propertyInfos = typeof(T).GetProperties();
        // Mount MultipartForm
        foreach (var propertyInfo in propertyInfos)
        {
            var value = propertyInfo.GetValue(_obj);
            if (value is byte[] ||
                value is Stream ||
                value is List<Stream> ||
                value is List<byte[]>)
            {
                if (value is List<Stream> listStream)
                {
                    foreach (var file in listStream)
                        if(file != null)
                            formContent.Add(new StreamContent(file), propertyInfo.Name, genericFileName);
                }else if (value is List<byte[]> listByteArray)
                {
                    foreach (var file in listByteArray)
                        if(file != null)
                            formContent.Add(new ByteArrayContent(file), propertyInfo.Name, genericFileName);
                }else
                    formContent.Add(getFileContent(value), propertyInfo.Name, genericFileName);
            }
            else if(value != null)
            {
                string output = value.ToString();
                if (!String.IsNullOrEmpty(output))
                {
                    formContent.Add(new StringContent(output), propertyInfo.Name);
                }
            }
        }
        return formContent;
    }
    private HttpContent getFileContent(object obj)
    {
        if (obj is Stream stream)
        {
            return new StreamContent(stream);
        } else if (obj is byte[] byteArray)
        {
            return new ByteArrayContent(byteArray);
        }
        else
        {
            throw new Exception("Type not valid to create a HttpContent of file");
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Veja que este código suporta Stream, byte[] e até mesmo uma lista destes tipos, como parâmetro de arquivo. Observe também que o foreach busca properties, este código não faz a conversão de fields.

O código abaixo mostra um exemplo de como utilizar.

class Program
{
    private static string _rootUrl = "http://localhost:8080/tests/formdata";

    public class ObjectForm
    {
        public string Param { get; set; }
        public List<Stream> File { get; set; }
        public ObjectForm()
        {
            File = new List<Stream>();
        }
    }
    static void Main(string[] args)
    {
        var client = new HttpClient();

        var obj = new ObjectForm();
        obj.Param = "String Param";
        obj.File.Add(new FileStream("Files/File1.txt", FileMode.Open, FileAccess.Read));
        obj.File.Add(new FileStream("Files/File2.json", FileMode.Open, FileAccess.Read));

        MultipartFormDataContent formdata = new MultipartFormDataContentParser<ObjectForm>(obj).Parse();

        HttpResponseMessage response = client.PostAsync(_rootUrl, formdata).Result;
        Console.WriteLine(response.Content.ReadAsStringAsync().Result);
    }
}
Enter fullscreen mode Exit fullscreen mode
💖 💪 🙅 🚩
raiitto
Railson Ferreira de Souza

Posted on February 19, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related