ASP.NET Webapi: How to Perform a Multipart Post with File Upload Using Webapi Httpclient

ASP.NET WebApi: how to perform a multipart post with file upload using WebApi HttpClient

After much trial and error, here's code that actually works:

using (var client = new HttpClient())
{
using (var content = new MultipartFormDataContent())
{
var values = new[]
{
new KeyValuePair<string, string>("Foo", "Bar"),
new KeyValuePair<string, string>("More", "Less"),
};

foreach (var keyValuePair in values)
{
content.Add(new StringContent(keyValuePair.Value), keyValuePair.Key);
}

var fileContent = new ByteArrayContent(System.IO.File.ReadAllBytes(fileName));
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "Foo.txt"
};
content.Add(fileContent);

var requestUri = "/api/action";
var result = client.PostAsync(requestUri, content).Result;
}
}

Upload Files with HttpClient to ASP.NET WebApi 2

I created two new empty projects, one for webapi and one for httpclient.

I tried copying the existing client code and the existing server code to the new projects.

I discovered that the problem was the parameter to the webapi action, it seems to broke the stream.

So if someone need to upload multipart form data to ASP.NET WebApi don't use parameters in the action, it won't resolve any model and it broke the multipart stream.

Posting file with HttpClient to a Web Api

Edit:

So since Web Api 2.1 it is possible to use BSON, a "JSON-like" Format, which is able to send binary formatted data. In the linked Article you'll even find an example using HttpClient.

Before the Introduction of BSON a common way around the limitation of JSON has been to encode the binary as base64.

Orig:

The short of it is you can't simply send a byte[] as a Json Property.

Possible work-arounds are:

  1. Base64 parsing at Client/Server
  2. Another possibility that i haven't been aware of until now is BSON. Look at the official Docs and this Thread for more info.

Maybe someone else has something to add to that list.

Cheers,

C# HttpClient 4.5 multipart/form-data upload

my result looks like this:

public static async Task<string> Upload(byte[] image)
{
using (var client = new HttpClient())
{
using (var content =
new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(CultureInfo.InvariantCulture)))
{
content.Add(new StreamContent(new MemoryStream(image)), "bilddatei", "upload.jpg");

using (
var message =
await client.PostAsync("http://www.directupload.net/index.php?mode=upload", content))
{
var input = await message.Content.ReadAsStringAsync();

return !string.IsNullOrWhiteSpace(input) ? Regex.Match(input, @"http://\w*\.directupload\.net/images/\d*/\w*\.[a-z]{3}").Value : null;
}
}
}
}

Upload Zip files to ASP.NET Core WebAPI service with HttpClient but IFormData argument is always null

You are doing a couple of things wrong:

public async Task<IActionResult> AddFileToTranscription([FromForm] IFormFile file)

❌ You don't need [FromFile] attribute.

❌ Your file argument name is file but you haven't defined it when you are uploading files, in the client.

❌ You don't need to add ContentDisposition and set it as attachment because it's for the response, not the request! (1)


✅ Server:

public async Task<IActionResult> AddFileToTranscription( IFormFile file)
{
using (var sr = new StreamReader(file.OpenReadStream()))
{
var content = await sr.ReadToEndAsync();
return Ok(content);
}
}

✅ Client:

client.BaseAddress = new Uri("http://localhost:62337/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

string filepath = @"C:\Users\uic10950\Desktop\Meeting2Text\RecordingApp\bin\mixedaudio.zip";
string filename = "mixedaudio.zip";

MultipartFormDataContent content = new MultipartFormDataContent();
ByteArrayContent fileContent = new ByteArrayContent(System.IO.File.ReadAllBytes(filepath));

// ➡ ✅ important change fileContent, form-input-name, real-file-name
content.Add(fileContent, "file", filename);

HttpResponseMessage response = await client.PostAsync("api/transcriptions/recording", content);
string returnString = await response.Content.ReadAsAsync<string>();

MultipartFormDataContent.Add method has a couple of overloads for adding form-data, you must use this overload:

public void Add (System.Net.Http.HttpContent content, string name, string fileName);

Conclusion:

Whatever your IFormData argument is, you need to upload or send requests whit that name!


  1. In a regular HTTP response, the Content-Disposition response header is a header indicating if the content is expected to be displayed inline in the browser, that is, as a Web page or as part of a Web page, or as an attachment, that is downloaded and saved locally.

How to upload file to server with HTTP POST multipart/form-data?

Here's my final working code. My web service needed one file (POST parameter name was "file") & a string value (POST parameter name was "userid").

/// <summary>
/// Occurs when upload backup application bar button is clicked. Author : Farhan Ghumra
/// </summary>
private async void btnUploadBackup_Click(object sender, EventArgs e)
{
var dbFile = await ApplicationData.Current.LocalFolder.GetFileAsync(Util.DBNAME);
var fileBytes = await GetBytesAsync(dbFile);
var Params = new Dictionary<string, string> { { "userid", "9" } };
UploadFilesToServer(new Uri(Util.UPLOAD_BACKUP), Params, Path.GetFileName(dbFile.Path), "application/octet-stream", fileBytes);
}

/// <summary>
/// Creates HTTP POST request & uploads database to server. Author : Farhan Ghumra
/// </summary>
private void UploadFilesToServer(Uri uri, Dictionary<string, string> data, string fileName, string fileContentType, byte[] fileData)
{
string boundary = "----------" + DateTime.Now.Ticks.ToString("x");
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);
httpWebRequest.ContentType = "multipart/form-data; boundary=" + boundary;
httpWebRequest.Method = "POST";
httpWebRequest.BeginGetRequestStream((result) =>
{
try
{
HttpWebRequest request = (HttpWebRequest)result.AsyncState;
using (Stream requestStream = request.EndGetRequestStream(result))
{
WriteMultipartForm(requestStream, boundary, data, fileName, fileContentType, fileData);
}
request.BeginGetResponse(a =>
{
try
{
var response = request.EndGetResponse(a);
var responseStream = response.GetResponseStream();
using (var sr = new StreamReader(responseStream))
{
using (StreamReader streamReader = new StreamReader(response.GetResponseStream()))
{
string responseString = streamReader.ReadToEnd();
//responseString is depend upon your web service.
if (responseString == "Success")
{
MessageBox.Show("Backup stored successfully on server.");
}
else
{
MessageBox.Show("Error occurred while uploading backup on server.");
}
}
}
}
catch (Exception)
{

}
}, null);
}
catch (Exception)
{

}
}, httpWebRequest);
}

/// <summary>
/// Writes multi part HTTP POST request. Author : Farhan Ghumra
/// </summary>
private void WriteMultipartForm(Stream s, string boundary, Dictionary<string, string> data, string fileName, string fileContentType, byte[] fileData)
{
/// The first boundary
byte[] boundarybytes = Encoding.UTF8.GetBytes("--" + boundary + "\r\n");
/// the last boundary.
byte[] trailer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
/// the form data, properly formatted
string formdataTemplate = "Content-Dis-data; name=\"{0}\"\r\n\r\n{1}";
/// the form-data file upload, properly formatted
string fileheaderTemplate = "Content-Dis-data; name=\"{0}\"; filename=\"{1}\";\r\nContent-Type: {2}\r\n\r\n";

/// Added to track if we need a CRLF or not.
bool bNeedsCRLF = false;

if (data != null)
{
foreach (string key in data.Keys)
{
/// if we need to drop a CRLF, do that.
if (bNeedsCRLF)
WriteToStream(s, "\r\n");

/// Write the boundary.
WriteToStream(s, boundarybytes);

/// Write the key.
WriteToStream(s, string.Format(formdataTemplate, key, data[key]));
bNeedsCRLF = true;
}
}

/// If we don't have keys, we don't need a crlf.
if (bNeedsCRLF)
WriteToStream(s, "\r\n");

WriteToStream(s, boundarybytes);
WriteToStream(s, string.Format(fileheaderTemplate, "file", fileName, fileContentType));
/// Write the file data to the stream.
WriteToStream(s, fileData);
WriteToStream(s, trailer);
}

/// <summary>
/// Writes string to stream. Author : Farhan Ghumra
/// </summary>
private void WriteToStream(Stream s, string txt)
{
byte[] bytes = Encoding.UTF8.GetBytes(txt);
s.Write(bytes, 0, bytes.Length);
}

/// <summary>
/// Writes byte array to stream. Author : Farhan Ghumra
/// </summary>
private void WriteToStream(Stream s, byte[] bytes)
{
s.Write(bytes, 0, bytes.Length);
}

/// <summary>
/// Returns byte array from StorageFile. Author : Farhan Ghumra
/// </summary>
private async Task<byte[]> GetBytesAsync(StorageFile file)
{
byte[] fileBytes = null;
using (var stream = await file.OpenReadAsync())
{
fileBytes = new byte[stream.Size];
using (var reader = new DataReader(stream))
{
await reader.LoadAsync((uint)stream.Size);
reader.ReadBytes(fileBytes);
}
}

return fileBytes;
}

I am very much thankful to Darin Rousseau for helping me.



Related Topics



Leave a reply



Submit