MultipartFormDataContent parsing - c#

I'm trying to send a request to this using MultipartFormDataContent , but i want to upload a media in this request :
The original script is this one, but it's not working as it need the "test.png" to be sent from file :
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://dezgo.p.rapidapi.com/image2image"),
Headers =
{
{ "X-RapidAPI-Key", "API_KEY" },
{ "X-RapidAPI-Host", "dezgo.p.rapidapi.com" },
},
Content = new MultipartFormDataContent
{
new StringContent("stablediffusion_1_5")
{
Headers =
{
ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "model",
}
}
},
new StringContent("0.8")
{
Headers =
{
ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "strength",
}
}
},
new StringContent("8")
{
Headers =
{
ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "guidance",
}
}
},
new StringContent("change color to blue")
{
Headers =
{
ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "prompt",
}
}
},
new StringContent("30")
{
Headers =
{
ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "steps",
}
}
},
new StringContent("1")
{
Headers =
{
ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "upscale",
}
}
},
new StringContent("dpm")
{
Headers =
{
ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "sampler",
}
}
},
new StringContent("")
{
Headers =
{
ContentType = new MediaTypeHeaderValue("application/octet-stream"),
ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "init_image",
FileName = "test.png",
}
}
},
},
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}
So, what i tried is to reconstruct the MultipartFormDataContent like this but it return Error 400 (Bad Request):
string filePath = "test.png";
var bytefile = AuthGetFileData(filePath);
var fileContent = new ByteArrayContent(bytefile);
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
var formData = new MultipartFormDataContent();
formData.Add(new StringContent("stablediffusion_1_5"), new ContentDispositionHeaderValue("form-data").Name = "model");
formData.Add(new StringContent("0.8"), new ContentDispositionHeaderValue("form-data").Name = "strength");
formData.Add(new StringContent("8"), new ContentDispositionHeaderValue("form-data").Name = "guidance");
formData.Add(new StringContent("a man"), new ContentDispositionHeaderValue("form-data").Name = "prompt");
formData.Add(new StringContent("30"), new ContentDispositionHeaderValue("form-data").Name = "steps");
formData.Add(new StringContent("1"), new ContentDispositionHeaderValue("form-data").Name = "upscale");
formData.Add(new StringContent("dpm"), new ContentDispositionHeaderValue("form-data").Name = "sampler");
formData.Add(new StreamContent(new MemoryStream(bytefile)), "init_image", "test.png");
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://dezgo.p.rapidapi.com/image2image"),
Headers =
{
{ "X-RapidAPI-Key", "API_KEY" },
{ "X-RapidAPI-Host", "dezgo.p.rapidapi.com" },
},
Content = formData,
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}

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

Bad Request with no reason

I am attempting to upgrade to newest APNS connectivity functionality but when I submit a request I get a http 400 bad request result with no reason. What am I missing / doing wrong?
Method for sending below:
public async void SendAsync(string deviceToken, string p8privateKey, string p8privateKeyId, string teamId)
{
var path = $"/3/device/{deviceToken}";
var obj = new
{
aps = new
{
alert = "test00001"
}
};
var json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
var request = new HttpRequestMessage(HttpMethod.Post, new Uri("https://api.development.push.apple.com:443" + path))
{
Version = new Version(2, 0)
};
string jwToken = CreateJwtToken(p8privateKey, p8privateKeyId, teamId);
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", jwToken);
request.Headers.TryAddWithoutValidation(":method", "POST");
request.Headers.TryAddWithoutValidation(":path", path);
request.Headers.Add("apns-topic", "com.the-app");
request.Content = new StringContent(json);
string sReq = JsonConvert.SerializeObject(request);
string jsonContent = request.Content.ReadAsStringAsync().Result;
WinHttpHandler handler = new WinHttpHandler();
HttpClient http = new HttpClient(handler);
var t = await http.SendAsync(request);
}
Here are the other used methods:
private static string CreateJwtToken(string p8privateKeyId, string p8privateKey, string teamId)
{
var header = JsonHelper.Serialize(new { alg = "ES256", kid = p8privateKeyId });
var payload = JsonHelper.Serialize(new { iss = teamId, iat = ToEpoch(DateTime.UtcNow) });
var key = CngKey.Import(Convert.FromBase64String(p8privateKey), CngKeyBlobFormat.Pkcs8PrivateBlob);
using (var dsa = new ECDsaCng(key))
{
dsa.HashAlgorithm = CngAlgorithm.Sha256;
var headerBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(header));
var payloadBasae64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(payload));
var unsignedJwtData = $"{headerBase64}.{payloadBasae64}";
var signature = dsa.SignData(Encoding.UTF8.GetBytes(unsignedJwtData));
return $"{unsignedJwtData}.{Convert.ToBase64String(signature)}";
}
}
private static int ToEpoch(DateTime time)
{
var span = DateTime.UtcNow - new DateTime(1970, 1, 1);
return Convert.ToInt32(span.TotalSeconds);
}
I have limited to the payload to what I think is the bear minimum requirements. I am new to jwt/http2 and APNS.
I could very well be missing something simple.

How to post form-data IFormFile with HttpClient?

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

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

Twitter API invalid or expired token

I'm trying to use the below code but for some reason I'm getting an invalid or expired token it seemed to work once but never again.
Any ideas? (consumerKey and consumerSecret are constants generated in the class.)
public ActionResult Index()
{
string twitterAccount = System.Configuration.ConfigurationManager.AppSettings["twitterAccount"];
JsonDeserializer jsonDeserializer = new JsonDeserializer();
var model = new TwitterVM.LandingModel();
var qs = GetToken();
string oauthToken = qs["oauth_token"];
string oauthTokenSecret = qs["oauth_token_secret"];
RestClient client = new RestClient("https://api.twitter.com/1.1")
{
Authenticator = OAuth1Authenticator.ForProtectedResource(consumerKey, consumerSecret, oauthToken, oauthTokenSecret)
};
RestRequest request = new RestRequest("statuses/user_timeline", Method.GET);
request.Parameters.Add(new Parameter()
{
Name = "screen_name",
Value = twitterAccount,
Type = ParameterType.GetOrPost
});
request.Parameters.Add(new Parameter()
{
Name = "count",
Value = 10,
Type = ParameterType.GetOrPost
});
request.Parameters.Add(new Parameter()
{
Name = "include_rts",
Value = true,
Type = ParameterType.GetOrPost
});
request.Parameters.Add(new Parameter()
{
Name = "include_entities",
Value = true,
Type = ParameterType.GetOrPost
});
IRestResponse response = client.Execute(request);
model.Tweets =
jsonDeserializer.Deserialize<List<TwitterVM.Tweet>>(response);
return View(model);
}
private NameValueCollection GetToken()
{
RestClient client = new RestClient("https://api.twitter.com") { Authenticator = OAuth1Authenticator.ForRequestToken(consumerKey, consumerSecret) };
//Do the auth shit...
RestRequest request = new RestRequest("oauth/request_token", Method.POST);
IRestResponse response = client.Execute(request);
return HttpUtility.ParseQueryString(response.Content);
}
Using Twitter's OAuth2 API (https://api.twitter.com/oauth2/token)
See https://dev.twitter.com/oauth/application-only for details....
var client = await CreateHttpClient("....", "....");
//don't dispose this client and use for subsequent API calls
var screenName = "....";
var count = 10;
var include_rts = true;
var url = $"https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name={screenName}&include_rts={include_rts}&count={count}";
var json = await client.GetStringAsync(url);
public static async Task<HttpClient> CreateHttpClient(string consumerKey, string consumerSecret)
{
var bearerToken = Convert.ToBase64String(Encoding.UTF8.GetBytes(consumerKey + ":" + consumerSecret));
string url = "https://api.twitter.com/oauth2/token";
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "Basic " + bearerToken);
var resp = await client.PostAsync(url, new StringContent("grant_type=client_credentials", Encoding.UTF8, "application/x-www-form-urlencoded")).ConfigureAwait(false);
resp.EnsureSuccessStatusCode();
var result = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
var jObj = new JavaScriptSerializer().Deserialize<Dictionary<string,string>>(result);
if (jObj["token_type"] != "bearer") throw new Exception("Invalid Response From Twitter/OAuth");
client.DefaultRequestHeaders.Remove("Authorization");
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "Bearer " + jObj["access_token"]);
return client;
}

Categories

Resources