How i can post file to web API from C#? - c#

I need to post a file from asp application to an API
the file will be uploaded through <asp:FileUpload />
in the back end, i will receive the file and send it to Web API method
the web API method will contain the code
var root = HttpContext.Current.Server.MapPath("~/App_Data/Uploadfiles");
var provider = new MultipartFormDataStreamProvider(root);
var result = await Request.Content.ReadAsMultipartAsync(provider);
the asp page will has the code
using (System.IO.Stream fs = fuID.PostedFile.InputStream)
{
System.IO.BinaryReader br = new System.IO.BinaryReader(fs);
Byte[] bytes = br.ReadBytes((Int32)fs.Length);
string base64String = Convert.ToBase64String(bytes, 0, bytes.Length);
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), "http://localhost:5000/path"))
{
request.Headers.TryAddWithoutValidation("Accept", "application/json, text/plain, */*");
request.Headers.TryAddWithoutValidation("Authorization", "Bearer " + AppUserContext.Token);
request.Headers.TryAddWithoutValidation("x-language", "ar");
// Iam Not Sure of this line
request.Content = new StringContent("Content-Disposition:" + base64String, Encoding.UTF8, "multipart/form-data");
var response = httpClient.SendAsync(request).Result;
}
}
}
i need to know how i can send the file in the body of the request what to write in this line
request.Content = new StringContent("Content-Disposition:" + base64String, Encoding.UTF8, "multipart/form-data");

pf is the posted file
then use
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AppUserContext.Token);
client.DefaultRequestHeaders.Add("x-language", "ar");
using (var stream = pf.InputStream)
{
var content = new MultipartFormDataContent();
var file_content = new ByteArrayContent(new StreamContent(stream).ReadAsByteArrayAsync().Result);
file_content.Headers.ContentType = new MediaTypeHeaderValue(pf.ContentType);
file_content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
FileName = JsonConvert.SerializeObject(pf.FileName),
};
content.Add(file_content);
var url = "URL Here";
var response = client.PostAsync(url, content).Result;
response.EnsureSuccessStatusCode();
}
}

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)
{
}
}

PDF corrupted when uploading a document with .NET HttpClient

I am trying to upload a document to this AdobeSign API endpoint
While I have found a way to do it succesfully with the RestSharp RestClient with my below code:
var client = new RestClient("https://api.na2.echosign.com/api/rest/v6/transientDocuments");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer MyIntegratorKey");
var bytes = Convert.FromBase64String(base64Document);
var contents = new MemoryStream(bytes);
request.Files.Add(new FileParameter
{
Name = "File",
Writer = (s) =>
{
var stream = contents;
stream.CopyTo(s);
stream.Dispose();
},
FileName = "Test2.pdf",
ContentType = null,
ContentLength = bytes.Length
});
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
I am having issues when I try to use the .NET HttpClient. My below code successfully upload the document (HTTP 201 returned by Adobe) but the document is completely messed up when the signers open it.
Doesn't the .NET HttpClient support file uploads ? is there something wrong with my stream ?
Thank you in advance
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = AuthenticationHeaderValue.Parse("Bearer IntegratorKey");
using (var content = new MultipartFormDataContent())
{
content.Add(new StreamContent(new MemoryStream(Convert.FromBase64String(document.EmbeddedContent))), "File", "Test2.pdf");
using (
var message =
await client.PostAsync("https://api.na2.echosign.com/api/rest/v6/transientDocuments", content))
{
var input = await message.Content.ReadAsStringAsync();
Console.WriteLine(input);
}
}
}

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;
}

Send an form-data post request with .Net framework HttpClient class containing a file

I need to recreate this request I made in Postman with C#, I found that the HttpClient class solves most of my problems, but this time I couldn't solve it on my own.
I embbeded an image with an example of the very post request.
POST REQUEST IN POSTMAN
There are three text paramethers and one file I need to send, with a content-type of form-data, the file needs to be a .json.
I tried constructing the POST request in many ways; this is my last version:
string endpoint = $"{Endpoint}/captcha";
string token_paramsJSON = JsonConvert.SerializeObject(v3Request.token_params);
Hashtable ParametrosPOSTCaptcha = GetV3POSTParams(v3Request);
UnicodeEncoding uniEncoding = new UnicodeEncoding();
using (Stream ms = new MemoryStream()) {
var sw = new StreamWriter(ms, uniEncoding);
sw.Write(token_paramsJSON);
sw.Flush();
ms.Seek(0, SeekOrigin.Begin);
using (MultipartFormDataContent form = new MultipartFormDataContent())
{
form.Add(new StringContent(v3Request.username), "username");
form.Add(new StringContent(v3Request.password), "password");
form.Add(new StringContent(v3Request.type.ToString()), "type");
form.Add(new StreamContent(ms));
var response = await _httpClient.PostAsync(endpoint, form);
string ResponseTest = await GetResponseText(response);
}
}
With this code, I successfully establish a connection with the endpoint, send the username and password.
But the response differs from the one I get with Postman using the same paramethers:
Postman: x=0&xx=1892036372&xxx=&xxxxx=1
The actual response I get is this:
HttpClient: {"error": "not-logged-in"}
Thanks in advance!
Finally, I could solve it using the following implementation:
string endpoint = $"{Endpoint}/endpointName";
string token_paramsJSON = JsonConvert.SerializeObject(v3Request.token_params, Formatting.Indented);
Dictionary<string,string> PostParams = GetPOSTParams(v3Request);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, endpoint);
UnicodeEncoding uniEncoding = new UnicodeEncoding();
using (MultipartFormDataContent form = new MultipartFormDataContent())
{
foreach(var field in PostParams)
{
StringContent content = new StringContent(field.Value);
content.Headers.ContentType = null;
form.Add(content, field.Key);
}
var JsonFile = new StringContent(token_paramsJSON);
JsonFile.Headers.ContentType = new MediaTypeHeaderValue("application/json");
JsonFile.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "\"token_params\"",
FileName = "\"token.json\""
};
form.Add(JsonFile);
request.Content = form;
var response = await _httpClient.SendAsync(request, CancellationToken.None);
return await GetCaptchaFromResponse(response);
}

Sending multipart/related content to SOAP service .NET Core

I'm trying to set the headers of my HttpRequestMessage for sending a multipart/related HTTP message to a SOAP service.
The headers need to look to something like this :
multipart/related;boundary=MIMEBoundaryurn_uuid_7B970E2B89C4446286DDFDBFF7F19581; type="application/xop+xml"; start="0.urn:uuid:4628599A1A934415B3EFB15A1888004B#ws.jboss.org>"; start-info="application/soap+xml"; action="urn:ihe:iti:2007:ProvideAndRegisterDocumentSet-b"
But I can't figure out how to set them up with my HttpRequestMessage.
Here's my code :
using (var client = new HttpClient(handler))
{
var request = new HttpRequestMessage()
{
RequestUri = new Uri(Host),
Method = HttpMethod.Post
};
var boundary = Guid.NewGuid().ToString();
var bytes = new ByteArrayContent(doc);
bytes.Headers.ContentType = new MediaTypeHeaderValue("text/xml");
var multi = new MultipartContent("related", boundary) {
new StringContent(xml.ToString(), Encoding.UTF8, "text/xml"),
bytes
};
request.Content = multi;
Log.Information(request.Headers.ToString());
Log.Information(request.Content.Headers.ToString());
Log.Information(request.Content.ToString());
var response = client.SendAsync(request).Result;
if (!response.IsSuccessStatusCode)
throw new Exception($"Request resulted in status :{response.StatusCode}");
var stream = response.Content.ReadAsStreamAsync().Result;
using (var sr = new StreamReader(stream))
{
var soapResponse = XDocument.Load(sr);
Log.Information("Soap response : " + soapResponse);
}
}

Categories

Resources