Sebastian
Sebastian

Reputation: 87

set MultipartFormDataContent for multipart/form-data file upload right with HttpClient

The following code works:

string UploadWithHttpRequest(string url, string filePath, string fileName)
{
    try
    {
        byte[] fileByteArray = File.ReadAllBytes(filePath);

        string formDataBoundary = $"----------{Guid.NewGuid():N}";
        string contentType = "multipart/form-data; boundary=" + formDataBoundary;
        byte[] formData = GetMultipartFormDataForUpload(fileByteArray, fileName, contentType, formDataBoundary);
        var request = WebRequest.Create(url) as HttpWebRequest;

        request.Method = "POST";
        request.ContentType = contentType;
        request.UserAgent = Credentials.UserName;
        request.CookieContainer = new CookieContainer();
        request.ContentLength = formData.Length;
        request.Credentials = Credentials;

        using (Stream RequestStream = request.GetRequestStream())
        {
            RequestStream.Write(formData, 0, formData.Length);
            RequestStream.Close();
        }

        var response = request.GetResponse() as HttpWebResponse;

        var ResponseReader = new StreamReader(response.GetResponseStream());
        string FullResponse = ResponseReader.ReadToEnd();
        response.Close();
        return FullResponse;
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

byte[] GetMultipartFormDataForUpload(byte[] byteArray, string fileName, string contentType, string Boundary)
{
    Stream FormDataStream = new MemoryStream();
    string Header = string.Format("--{0}" + Environment.NewLine + "Content-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"" 
                                    + Environment.NewLine + Environment.NewLine, Boundary, "file", fileName);
    FormDataStream.Write(Encoding.UTF8.GetBytes(Header), 0, Encoding.UTF8.GetByteCount(Header));
    FormDataStream.Write(byteArray, 0, byteArray.Length);

    string Footer = Environment.NewLine + "--" + Boundary + "--" + Environment.NewLine;
    FormDataStream.Write(Encoding.UTF8.GetBytes(Footer), 0, Encoding.UTF8.GetByteCount(Footer));
    FormDataStream.Position = 0L;
    var FormData = new byte[(int)(FormDataStream.Length - 1L + 1)];
    FormDataStream.Read(FormData, 0, FormData.Length);
    FormDataStream.Close();
    return FormData;
}

But instead of using HttpRequest I'd like to use HttpClient and instead of doing all the encoding manually (especially in GetMultipartFormDataForUpload) I'd like to use the class MultipartFormDataContent. When I try this, I always get a 500 from the server. This is what I have tried so far:

async Task<string> UploadWithHttpClient(string url, string filePath, string fileName)
{
    try
    {
        byte[] fileByteArray = File.ReadAllBytes(filePath);

        var content = new MultipartFormDataContent("------------" + Guid.NewGuid());

        var byteArrayContent = new ByteArrayContent(fileByteArray, 0, fileByteArray.Length);

        //Option 1
        byteArrayContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
        {
            Name = "file",
            FileName = fileName
        };

        //Option 2
        content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
        {
            Name = "file",
            FileName = fileName
        };
        content.Add(byteArrayContent, "file");

        var client = new HttpClient();
        var response = await client.PostAsync(url, content);
        var result = await response.Content.ReadAsStringAsync();

        
        return result;
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

What is the right way to replace the httprequest with the httpclient? Where does the content-disposition header belong (is one of the options I have tried correct)? If yes what else is my problem?

Upvotes: 2

Views: 10430

Answers (1)

Sebastian
Sebastian

Reputation: 87

the following code worked for me in the end:

async Task<string> UploadWithHttpClient(string url, string filePath, string fileName)
{
    try
    {
        byte[] fileByteArray = File.ReadAllBytes(filePath);

        var content = new MultipartFormDataContent("------------" + Guid.NewGuid());

        var byteArrayContent = new ByteArrayContent(fileByteArray);

        byteArrayContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/pdf");

        content.Add(byteArrayContent, "\"file\"", $"\"{fileName}\"");

        var client = new HttpClient();
        var response = await client.PostAsync(url, content);
        var result = await response.Content.ReadAsStringAsync();

        
        return result;
    }
    catch (Exception ex)
    {
        throw ex;
    }
}
```

Upvotes: 2

Related Questions