How to post form-data IFormFile with HttpClient? - c#

I have backend endpoint Task<ActionResult> Post(IFormFile csvFile) and I need to call this endpoint from HttpClient. Currently I am getting Unsupported media type error.
Here is my code:
var filePath = Path.Combine("IntegrationTests", "file.csv");
var gg = File.ReadAllBytes(filePath);
var byteArrayContent = new ByteArrayContent(gg);
var postResponse = await _client.PostAsync("offers", new MultipartFormDataContent
{
{byteArrayContent }
});

You need to specify parameter name in MultipartFormDataContent collection matching action parameter name (csvFile) and a random file name
var multipartContent = new MultipartFormDataContent();
multipartContent.Add(byteArrayContent, "csvFile", "filename");
var postResponse = await _client.PostAsync("offers", multipartContent);
or equivalent
var postResponse = await _client.PostAsync("offers", new MultipartFormDataContent {
{ byteArrayContent, "csvFile", "filename" }
});

Use this snippet:
const string url = "https://localhost:5001/api/Upload";
const string filePath = #"C:\Path\To\File.png";
using (var httpClient = new HttpClient())
{
using (var form = new MultipartFormDataContent())
{
using (var fs = File.OpenRead(filePath))
{
using (var streamContent = new StreamContent(fs))
{
using (var fileContent = new ByteArrayContent(await streamContent.ReadAsByteArrayAsync()))
{
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
// "file" parameter name should be the same as the server side input parameter name
form.Add(fileContent, "file", Path.GetFileName(filePath));
HttpResponseMessage response = await httpClient.PostAsync(url, form);
}
}
}
}
}

This worked for me as a generic
public static Task<HttpResponseMessage> PostFormDataAsync<T>(this HttpClient httpClient, string url, string token, T data)
{
var content = new MultipartFormDataContent();
foreach (var prop in data.GetType().GetProperties())
{
var value = prop.GetValue(data);
if (value is FormFile)
{
var file = value as FormFile;
content.Add(new StreamContent(file.OpenReadStream()), prop.Name, file.FileName);
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") { Name = prop.Name, FileName = file.FileName };
}
else
{
content.Add(new StringContent(JsonConvert.SerializeObject(value)), prop.Name);
}
}
if (!string.IsNullOrWhiteSpace(token))
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
return httpClient.PostAsync(url, content);
}

Solved by using this code:
const string fileName = "csvFile.csv";
var filePath = Path.Combine("IntegrationTests", fileName);
var bytes = File.ReadAllBytes(filePath);
var form = new MultipartFormDataContent();
var content = new StreamContent(new MemoryStream(bytes));
form.Add(content, "csvFile");
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "csvFile",
FileName = fileName
};
content.Headers.Remove("Content-Type");
content.Headers.Add("Content-Type", "application/octet-stream; boundary=----WebKitFormBoundaryMRxYYlVt8KWT8TU3");
form.Add(content);
//Act
var postResponse = await _sellerClient.PostAsync("items/upload", form);

Post the attachment as an MultipartFormDataContent
var type = typeof(Startup);
var stream = type.Assembly.GetManifestResourceStream(type, "Resources.New.docx");
var fileContent = new StreamContent(stream);
var data = new MultipartFormDataContent
{
{ fileContent, "file", "New.docx" }
};
var response = await _client.PostAsync("upload", multipartContent);
Source: https://medium.com/#woeterman_94/c-webapi-upload-files-to-a-controller-e5ccf288b0ca

Please see the following working code with .NET 5.0 Environment.
You send the file as a byte[] and receive it as a IFormFile in the API.
//api controller receiver
[HttpPost("SendBackupFiles")]
public IActionResult SendBackupFiles(IFormFile file)
{
var filePath = Path.GetTempFileName();
using (var stream = System.IO.File.Create(filePath))
file.CopyToAsync(stream);
}
//client code sender example, not optimized lol.
const string filePath = #"C:\temp\hallo.csv";
using (var httpClient = new HttpClient())
{
var form = new MultipartFormDataContent();
byte[] fileData = File.ReadAllBytes(filePath);
ByteArrayContent byteContent = new ByteArrayContent(fileData);
byteContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
form.Add(byteContent, "file", Path.GetFileName(filePath));
var result = httpClient.PostAsync("http://localhost:5070/..yourControllerName.../SendBackupFiles", form).ConfigureAwait(false).GetAwaiter().GetResult().Content.ReadAsStringAsync().Result;
}

Related

How to Pass value along with file upload through webclient C# [duplicate]

How can I send a file and form data with the HttpClient?
I have two ways to send a file or form data. But I want to send both like an HTML form. How can I do that? Thanks.
This is my code:
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
var client = new HttpClient();
var requestContent = new MultipartFormDataContent();
filename = openFileDialog1.FileName;
array = File.ReadAllBytes(filename);
var imageContent = new ByteArrayContent(array);
imageContent.Headers.ContentType = MediaTypeHeaderValue.Parse("audio/*");
requestContent.Add(imageContent, "audio", "audio.wav");
var values = new Dictionary<string, string>
{
{ "token", "b53b99534a137a71513548091271c44c" },
};
var content = new FormUrlEncodedContent(values);
requestContent.Add(content);
var response = await client.PostAsync("localhost", requestContent);
var responseString = await response.Content.ReadAsStringAsync();
txtbox.Text = responseString.ToString();
}
Here's code I'm using to post form information and a csv file
using (var httpClient = new HttpClient())
{
var surveyBytes = ConvertToByteArray(surveyResponse);
httpClient.DefaultRequestHeaders.Add("X-API-TOKEN", _apiToken);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var byteArrayContent = new ByteArrayContent(surveyBytes);
byteArrayContent.Headers.ContentType = MediaTypeHeaderValue.Parse("text/csv");
var response = await httpClient.PostAsync(_importUrl, new MultipartFormDataContent
{
{new StringContent(surveyId), "\"surveyId\""},
{byteArrayContent, "\"file\"", "\"feedback.csv\""}
});
return response;
}
This is for .net 4.5.
Note the \" in the MultipartFormDataContent. There is a bug in MultipartFormDataContent.
In 4.5.1 MultipartFormDataContent wraps the data with the correct quotes.
Update: This link to the bug no longer works since the have retired Microsoft Connect.
Here's code I'm using a method to send file and data from console to API
static async Task uploaddocAsync()
{
MultipartFormDataContent form = new MultipartFormDataContent();
Dictionary<string, string> parameters = new Dictionary<string, string>();
//parameters.Add("username", user.Username);
//parameters.Add("FullName", FullName);
HttpContent DictionaryItems = new FormUrlEncodedContent(parameters);
form.Add(DictionaryItems, "model");
try
{
var stream = new FileStream(#"D:\10th.jpeg", FileMode.Open);
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(#"http:\\xyz.in");
HttpContent content = new StringContent("");
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "uploadedFile1",
FileName = "uploadedFile1"
};
content = new StreamContent(stream);
form.Add(content, "uploadedFile1");
client.DefaultRequestHeaders.Add("Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.dsfdsfdsfdsfsdfkhjhjkhjk.vD056hXETFMXYxOaLZRwV7Ny1vj-tZySAWq6oybBr2w");
var response = client.PostAsync(#"\api\UploadDocuments\", form).Result;
var k = response.Content.ReadAsStringAsync().Result;
}
catch (Exception ex)
{
}
}

How to implement WebClient.UploadFileAsync with HttpClient? [duplicate]

Does anyone know how to use the HttpClient in .Net 4.5 with multipart/form-data upload?
I couldn't find any examples on the internet.
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;
}
}
}
}
It works more or less like this (example using an image/jpg file):
async public Task<HttpResponseMessage> UploadImage(string url, byte[] ImageData)
{
var requestContent = new MultipartFormDataContent();
// here you can specify boundary if you need---^
var imageContent = new ByteArrayContent(ImageData);
imageContent.Headers.ContentType =
MediaTypeHeaderValue.Parse("image/jpeg");
requestContent.Add(imageContent, "image", "image.jpg");
return await client.PostAsync(url, requestContent);
}
(You can requestContent.Add() whatever you want, take a look at the HttpContent descendant to see available types to pass in)
When completed, you'll find the response content inside HttpResponseMessage.Content that you can consume with HttpContent.ReadAs*Async.
This is an example of how to post string and file stream with HTTPClient using MultipartFormDataContent. The Content-Disposition and Content-Type need to be specified for each HTTPContent:
Here's my example. Hope it helps:
private static void Upload()
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("User-Agent", "CBS Brightcove API Service");
using (var content = new MultipartFormDataContent())
{
var path = #"C:\B2BAssetRoot\files\596086\596086.1.mp4";
string assetName = Path.GetFileName(path);
var request = new HTTPBrightCoveRequest()
{
Method = "create_video",
Parameters = new Params()
{
CreateMultipleRenditions = "true",
EncodeTo = EncodeTo.Mp4.ToString().ToUpper(),
Token = "x8sLalfXacgn-4CzhTBm7uaCxVAPjvKqTf1oXpwLVYYoCkejZUsYtg..",
Video = new Video()
{
Name = assetName,
ReferenceId = Guid.NewGuid().ToString(),
ShortDescription = assetName
}
}
};
//Content-Disposition: form-data; name="json"
var stringContent = new StringContent(JsonConvert.SerializeObject(request));
stringContent.Headers.Add("Content-Disposition", "form-data; name=\"json\"");
content.Add(stringContent, "json");
FileStream fs = File.OpenRead(path);
var streamContent = new StreamContent(fs);
streamContent.Headers.Add("Content-Type", "application/octet-stream");
//Content-Disposition: form-data; name="file"; filename="C:\B2BAssetRoot\files\596090\596090.1.mp4";
streamContent.Headers.Add("Content-Disposition", "form-data; name=\"file\"; filename=\"" + Path.GetFileName(path) + "\"");
content.Add(streamContent, "file", Path.GetFileName(path));
//content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
Task<HttpResponseMessage> message = client.PostAsync("http://api.brightcove.com/services/post", content);
var input = message.Result.Content.ReadAsStringAsync();
Console.WriteLine(input.Result);
Console.Read();
}
}
}
Try this its working for me.
private static async Task<object> Upload(string actionUrl)
{
Image newImage = Image.FromFile(#"Absolute Path of image");
ImageConverter _imageConverter = new ImageConverter();
byte[] paramFileStream= (byte[])_imageConverter.ConvertTo(newImage, typeof(byte[]));
var formContent = new MultipartFormDataContent
{
// Send form text values here
{new StringContent("value1"),"key1"},
{new StringContent("value2"),"key2" },
// Send Image Here
{new StreamContent(new MemoryStream(paramFileStream)),"imagekey","filename.jpg"}
};
var myHttpClient = new HttpClient();
var response = await myHttpClient.PostAsync(actionUrl.ToString(), formContent);
string stringContent = await response.Content.ReadAsStringAsync();
return response;
}
Here is another example on how to use HttpClient to upload a multipart/form-data.
It uploads a file to a REST API and includes the file itself (e.g. a JPG) and additional API parameters. The file is directly uploaded from local disk via FileStream.
See here for the full example including additional API specific logic.
public static async Task UploadFileAsync(string token, string path, string channels)
{
// we need to send a request with multipart/form-data
var multiForm = new MultipartFormDataContent();
// add API method parameters
multiForm.Add(new StringContent(token), "token");
multiForm.Add(new StringContent(channels), "channels");
// add file and directly upload it
FileStream fs = File.OpenRead(path);
multiForm.Add(new StreamContent(fs), "file", Path.GetFileName(path));
// send request to API
var url = "https://slack.com/api/files.upload";
var response = await client.PostAsync(url, multiForm);
}
Here's a complete sample that worked for me. The boundary value in the request is added automatically by .NET.
var url = "http://localhost/api/v1/yourendpointhere";
var filePath = #"C:\path\to\image.jpg";
HttpClient httpClient = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();
FileStream fs = File.OpenRead(filePath);
var streamContent = new StreamContent(fs);
var imageContent = new ByteArrayContent(streamContent.ReadAsByteArrayAsync().Result);
imageContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
form.Add(imageContent, "image", Path.GetFileName(filePath));
var response = httpClient.PostAsync(url, form).Result;
Example with preloader Dotnet 3.0 Core
ProgressMessageHandler processMessageHander = new ProgressMessageHandler();
processMessageHander.HttpSendProgress += (s, e) =>
{
if (e.ProgressPercentage > 0)
{
ProgressPercentage = e.ProgressPercentage;
TotalBytes = e.TotalBytes;
progressAction?.Invoke(progressFile);
}
};
using (var client = HttpClientFactory.Create(processMessageHander))
{
var uri = new Uri(transfer.BackEndUrl);
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", AccessToken);
using (MultipartFormDataContent multiForm = new MultipartFormDataContent())
{
multiForm.Add(new StringContent(FileId), "FileId");
multiForm.Add(new StringContent(FileName), "FileName");
string hash = "";
using (MD5 md5Hash = MD5.Create())
{
var sb = new StringBuilder();
foreach (var data in md5Hash.ComputeHash(File.ReadAllBytes(FullName)))
{
sb.Append(data.ToString("x2"));
}
hash = result.ToString();
}
multiForm.Add(new StringContent(hash), "Hash");
using (FileStream fs = File.OpenRead(FullName))
{
multiForm.Add(new StreamContent(fs), "file", Path.GetFileName(FullName));
var response = await client.PostAsync(uri, multiForm);
progressFile.Message = response.ToString();
if (response.IsSuccessStatusCode) {
progressAction?.Invoke(progressFile);
} else {
progressErrorAction?.Invoke(progressFile);
}
response.EnsureSuccessStatusCode();
}
}
}
I'm adding a code snippet which shows on how to post a file to an API which has been exposed over DELETE http verb. This is not a common case to upload a file with DELETE http verb but it is allowed. I've assumed Windows NTLM authentication for authorizing the call.
The problem that one might face is that all the overloads of HttpClient.DeleteAsync method have no parameters for HttpContent the way we get it in PostAsync method
var requestUri = new Uri("http://UrlOfTheApi");
using (var streamToPost = new MemoryStream("C:\temp.txt"))
using (var fileStreamContent = new StreamContent(streamToPost))
using (var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true })
using (var httpClient = new HttpClient(httpClientHandler, true))
using (var requestMessage = new HttpRequestMessage(HttpMethod.Delete, requestUri))
using (var formDataContent = new MultipartFormDataContent())
{
formDataContent.Add(fileStreamContent, "myFile", "temp.txt");
requestMessage.Content = formDataContent;
var response = httpClient.SendAsync(requestMessage).GetAwaiter().GetResult();
if (response.IsSuccessStatusCode)
{
// File upload was successfull
}
else
{
var erroResult = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
throw new Exception("Error on the server : " + erroResult);
}
}
You need below namespaces at the top of your C# file:
using System;
using System.Net;
using System.IO;
using System.Net.Http;
P.S. You are seeing a number of using blocks(IDisposable pattern) in the above code snippet which doesn't look very clean. Unfortunately, the syntax of using construct doesn't support initializing multiple variables in single statement.
X509Certificate clientKey1 = null;
clientKey1 = new X509Certificate(AppSetting["certificatePath"],
AppSetting["pswd"]);
string url = "https://EndPointAddress";
FileStream fs = File.OpenRead(FilePath);
var streamContent = new StreamContent(fs);
var FileContent = new ByteArrayContent(streamContent.ReadAsByteArrayAsync().Result);
FileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("ContentType");
var handler = new WebRequestHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ClientCertificates.Add(clientKey1);
handler.ServerCertificateValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) =>
{
return true;
};
using (var client = new HttpClient(handler))
{
// Post it
HttpResponseMessage httpResponseMessage = client.PostAsync(url, FileContent).Result;
if (!httpResponseMessage.IsSuccessStatusCode)
{
string ss = httpResponseMessage.StatusCode.ToString();
}
}
public async Task<object> PassImageWithText(IFormFile files)
{
byte[] data;
string result = "";
ByteArrayContent bytes;
MultipartFormDataContent multiForm = new MultipartFormDataContent();
try
{
using (var client = new HttpClient())
{
using (var br = new BinaryReader(files.OpenReadStream()))
{
data = br.ReadBytes((int)files.OpenReadStream().Length);
}
bytes = new ByteArrayContent(data);
multiForm.Add(bytes, "files", files.FileName);
multiForm.Add(new StringContent("value1"), "key1");
multiForm.Add(new StringContent("value2"), "key2");
var res = await client.PostAsync(_MEDIA_ADD_IMG_URL, multiForm);
}
}
catch (Exception e)
{
throw new Exception(e.ToString());
}
return result;
}

xamarin post not making it to api

Hi my xamarin post is not making it to my rest api.I keep getting "An error occure while sending the request" all my other posts work but just not this one. I have set network permissions as my login and geting data works. any help would be great. below is a code snippet.
public async Task<string> PostChecklist(string json)
{
try
{
JToken rootObject = JObject.Parse(json);
HttpClient httpClient = new HttpClient();
MultipartFormDataContent multipartContent = new MultipartFormDataContent();
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + TokenId);
httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
string sFile = (string)rootObject["Answers"]["Signature"];
//Get file
if (!File.Exists((string)rootObject["Answers"]["Signature"]))
{
return "no signature found";
}
FileStream fs = File.OpenRead((string)rootObject["Answers"]["Signature"]);
StreamContent streamContent = new StreamContent(fs);
streamContent.Headers.Add("Content-Type", "application/octet-stream");
multipartContent.Add(streamContent, "signature", "signature.png");
#region Upload images
JToken jobectImages = rootObject["Images"];
foreach (var item in jobectImages)
{
foreach (var internalitem in item)
{
foreach (var imageGroup in internalitem)
{
foreach (JObject image in imageGroup)
{
JToken tokenName, tokenFileName;
image.TryGetValue("FileName", out tokenName);
image.TryGetValue("FilePath", out tokenFileName);
string FileName = tokenName.ToString();
string FilePath = tokenFileName.ToString();
//Get file
FileStream fs2 = File.OpenRead(FilePath);
StreamContent streamContent2 = new StreamContent(fs);
streamContent2.Headers.Add("Content-Type", "application/octet-stream");
multipartContent.Add(streamContent2, FileName, FileName);
}
}
}
}
#endregion
var contentJson = new StringContent(json);
contentJson.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "JSONString"
};
var contentLong = new StringContent("26");
contentLong.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "Long"
};
var contentLat = new StringContent("96");
contentLat.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "Lat"
};
multipartContent.Add(contentJson);
multipartContent.Add(contentLong);
multipartContent.Add(contentLat);
var response = await httpClient.PostAsync(GlobalVariables.url + "/checkurl/answers/v12", multipartContent).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
Information = await response.Content.ReadAsStringAsync();
JObject jsonOther = JObject.Parse(Information);
if(((String)jsonOther["status"]) == "success")
{
return "";
}
else
{
return (String)jsonOther["message"];
}
}
else{
return "Server Error";
}
}
catch(Exception e)
{
return e.ToString();
}
}
Cool Looks like there was a problem with one of my MultipartFormDataContent when trying to attach images, if i dont attach an image it does work, so the Url post was breaking. Simulator cant take images so never had the problem.. Thanks anyways
MultipartFormDataContent has a bug with how it generates request content based on the order the headers and body are added.
For example
StreamContent streamContent = new StreamContent(fs);
streamContent.Headers.Add("Content-Type", "application/octet-stream");
multipartContent.Add(streamContent, "signature", "signature.png");
Will cause the content type header to be added before the content disposition header,
-----------------------------some boundary value here
Content-Type: application/octet-stream
Content-Disposition: form-data; name=signature; filename=signature.png
which is known to cause issues with how some servers read the body/content of the request
Instead make sure to set the content composition header first and also make sure that the name and file name are wrapped in double quotes before adding it to the multi-part form data content
StreamContent streamContent = new StreamContent(fs);
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") {
Name = "\"signature\"",
Filename = "\"signature.png\""
};
streamContent.Headers.Add("Content-Type", "application/octet-stream");
multipartContent.Add(streamContent);
The same will need to be done for the other section where images are added
//Get file
FileStream fs2 = File.OpenRead(FilePath);
StreamContent streamContent2 = new StreamContent(fs);
streamContent2.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") {
Name = string.Format("\"{0}\"", FileName),
Filename = string.Format("\"{0}\"", FileName),
};
streamContent2.Headers.Add("Content-Type", "application/octet-stream");
multipartContent.Add(streamContent2);

Uploaded file always with size zero

I am trying to upload the file to web API so I have the following code
public async Task<Token> upload(string fullMd5, IEnumerable<HttpPostedFileBase> files)
{
string uploadUrl = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Call CMS API
string jsonContent = string.Empty;
HttpClientHandler handler = new HttpClientHandler();
using (var client = new HttpClient())
{
using (var content = new MultipartFormDataContent())
{
var filesData = new MultipartFormDataContent();
foreach (var item in files)
{
HttpContent filecontent = new StreamContent(item.InputStream);
filecontent.Headers.ContentType = new MediaTypeHeaderValue(item.ContentType);
filecontent.Headers.ContentLength += item.InputStream.Length;
filecontent.Headers.ContentDisposition = new ContentDispositionHeaderValue("multipart/form-data")
{
Name = "file",
FileName = item.FileName,
};
content.Add(filecontent);
}
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + userObj.access_token);
client.DefaultRequestHeaders.Add("Api-version", "2.4");
client.DefaultRequestHeaders.Add("CMSId", UserId);
var response = await client.PostAsync(uploadUrl, content);
jsonContent = await response.Content.ReadAsStringAsync();
}
}
var result = JsonConvert.DeserializeObject<Token>(jsonContent);
return result;
}
}
the API receive the files but corrupted with zero size , the API works well as I tested using postman , I tried to save the files before sending using SaveAs and it worked well any problem in how I send the file
Try using postAsync like this with these headers
using (var client = new HttpClient(handler) {BaseAddress = new Uri(_host)})
{
var requestContent = new MultipartFormDataContent();
var fileContent = new StreamContent(fileInfo.OpenRead());
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
Name = "\"file\"",
FileName = "\"" + fileInfo.Name + "\""
};
fileContent.Headers.ContentType =
MediaTypeHeaderValue.Parse(MimeMapping.GetMimeMapping(fileInfo.Name));
var folderContent = new StringContent(folderId.ToString(CultureInfo.InvariantCulture));
requestContent.Add(fileContent);
requestContent.Add(folderContent, "\"folderId\"");
var result = client.PostAsync("Company/AddFile", requestContent).Result;
}

HttpClient Post photo WITH message to Facebook Graph

Issue
I am trying to upload a photo to the Facebook API WITH a message.
Code Snippet - Upload
requestUri = "https://graph.facebook.com/v2.0/me/photos?access_token=MyAccessToken"
var streamContent = new StreamContent(fileStream);
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "\"files\"",
FileName = "\"image.jpg\""
};
streamContent.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
var messageContent = new StringContent("message=HelloWorld");
var resultJson = webRequestClient.Post(requestUri, new MultipartFormDataContent()
{
messageContent,
streamContent,
});
Code - webRequestClient
public string Post(string uri, HttpContent postData)
{
return PostAsync(uri, postData).Result;
}
public async Task<string> PostAsync(string uri, HttpContent httpContent)
{
string resultStream;
using (var httpClient = new HttpClient())
{
var response = await httpClient.PostAsync(uri, httpContent);
response.EnsureSuccessStatusCode();
resultStream = await response.Content.ReadAsStringAsync();
}
return resultStream;
}
Notes
If I remove the "messageContent" : It uploads he picture
If I use MultipartContent : It uploads the picture but ignores my "message"
Don't bother for now why I don't do use the async functionality
When it fails I get "bad" requests
When I append the "message=helloworld" in the requestUri, it works, but that isn't the most flexible solution for in my architecture to deal with this issue.
Check this it will solve you problem, either you have to send the image via stream then you don't need to tell that the type is "image/jpeg" explicitly.
protected async void TakePictureAndUpload()
{
var ui = new CameraCaptureUI();
var file = await ui.CaptureFileAsync(CameraCaptureUIMode.Photo);
if (file != null)
{
byte[] myPicArray = await GetPhotoBytesAsync(file);
HttpClient httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("http://yourdomainname.com");
MultipartFormDataContent form = new MultipartFormDataContent();
HttpContent content = new ByteArrayContent(myPicArray);
form.Add(content, "media", "filename.jpg");
content = new StringContent("my-username");
form.Add(content, "username");
HttpResponseMessage response = await httpClient.PostAsync("directory/my-site.php", form);
}
}
public async Task<byte[]> GetPhotoBytesAsync(StorageFile file)
{
IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.Read);
var reader = new Windows.Storage.Streams.DataReader(fileStream.GetInputStreamAt(0));
await reader.LoadAsync((uint)fileStream.Size);
byte[] pixels = new byte[fileStream.Size];
reader.ReadBytes(pixels);
return pixels;
}

Categories

Resources