How to flash a spark core from C# - c#

I am trying to flash a spark core from a C# application. I keep getting { error: Nothing to do? } response.
Below is my code
var url = string.Format("https://api.spark.io/v1/devices/{0}", sparkDeviceID);
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accesstoken);
using (var formData = new MultipartFormDataContent())
{
HttpContent fileContent = new ByteArrayContent(Encoding.ASCII.GetBytes(rom));
//client.SendAsync()
formData.Add(fileContent, "file", "file");
var response = client.PutAsync(url, formData).Result;
if (!response.IsSuccessStatusCode)
throw new Exception("An error occurred during rom flash!");
var responseStream = response.Content.ReadAsStreamAsync().Result;
using (var reader = new StreamReader(responseStream, true))
{
var result = reader.ReadToEnd();
}
}
return true;
}
The documentation reads:
The API request should be encoded as multipart/form-data with a file field populated.
I believe the problem is the endpoint doesn't see the file. Any idea on how to resolve this?

Finally got it working.
The issue was the way .NET generated the content-disposition header for the file form data.
I used fiddler to compare the output of a successful put request to the put request that my code was generating:
Successful PUT request generated using CURL:
PUT http://127.0.0.1:8888/ HTTP/1.1
User-Agent: curl/7.33.0
Host: 127.0.0.1:8888
Accept: */*
Content-Length: 2861
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------5efcf64a370f13c8
--------------------------5efcf64a370f13c8
Content-Disposition: form-data; name="file"; filename="ms.ino"
Content-Type: application/octet-stream
...
My PUT request (unsuccessful):
PUT https://api.spark.io/v1/devices/{deviceid} HTTP/1.1
Authorization: Bearer {access_token}
Content-Type: multipart/form-data; boundary="135f5425-9342-4ffa-a645-99c04834026f"
Host: api.spark.io
Content-Length: 2878
Expect: 100-continue
--135f5425-9342-4ffa-a645-99c04834026f
Content-Type: application/octet-stream
Content-Disposition: form-data; name=file; filename=file.ino; filename*=utf-8''file.ino
...
If you'll notice the difference in the Content-Type for the actual file being sent:
Successful: Content-Disposition: form-data; name="file"; filename="ms.ino"
Unsuccessful: Content-Disposition: form-data; name=file; filename=file.ino; filename*=utf-8''file.ino
Most specifically, the resolution was to add quotes around the name attribute.
Resolution:
formData.Add(fileContent, "\"file\"", "file.ino");

Related

MultipartFormDataContent.Add StringContent is adding carraige return/linefeed to the name

formData.Add(sJobId,"job_id"); is sending "job_id\r\n" to the server
Here is my C# method:
public static async Task UploadAsync(string url, int job_id, string filename, string filePath) {
try {
// Submit the form using HttpClient and
// create form data as Multipart (enctype="multipart/form-data")
using (var fileStream = new StreamContent(System.IO.File.Open(filePath, FileMode.Open, FileAccess.Read)))
using (var formData = new MultipartFormDataContent()) {
StringContent sJobId = new StringContent(job_id.ToString());
StringContent sOthId = new StringContent(job_id.ToString());
// Try as I might C# adds a CrLf to the end of the job_id tag - so have to strip it in ruby
formData.Add(sOthId, "oth_id");
formData.Add(sJobId,"job_id");
fileStream.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
formData.Add(fileStream, "dt_file", filename);
HttpResponseMessage response = await HttpClient.PostAsync(url, formData);
// If the upload failed there is not a lot we can do
return;
}
} catch (Exception ex) {
// Not a lot we can do here - so just ignore it
System.Diagnostics.Debug.WriteLine($"Upload failed {ex.Message}");
}
}
This is what my Ruby puma server is receiving - see how oth_id and job_id have \r\n appended but "dt_file" does not.
Parameters: {"oth_id\r\n"=>"42157", "job_id\r\n"=>"42157", "dt_file"=>#<ActionDispatch::Http::UploadedFile:0x007f532817dc98 #tempfile=#<Tempfile:/tmp/RackMultipart20190715-37897-189ztb6.msg>, #original_filename="2019-07-15 164600.msg", #content_type="application/octet-stream", #headers="Content-Type: application/octet-stream\r\nContent-Disposition: form-data; name=dt_file; filename=\"2019-07-15 164600.msg\"; filename*=utf-8''2019-07-15%20164600.msg\r\n">}
How do I stop the formData.Add appending a \r\n to the name?
The raw message the application is sending to the server is
POST https://example.com/ HTTP/1.1
Host: example.com
Content-Type: multipart/form-data; boundary="93655e5a-b6b3-48d6-82c9-0d9aa99164cc"
Content-Length: 522
--93655e5a-b6b3-48d6-82c9-0d9aa99164cc
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=oth_id
1234
--93655e5a-b6b3-48d6-82c9-0d9aa99164cc
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=job_id
1234
--93655e5a-b6b3-48d6-82c9-0d9aa99164cc
Content-Type: application/octet-stream
Content-Disposition: form-data; name=dt_file; filename=myfile.txt; filename*=utf-8''myfile.txt
a,b,c,d
aa,"b,b","c
c",dd
aaa
--93655e5a-b6b3-48d6-82c9-0d9aa99164cc--
Have a look at the name values.
Looking at RFC 7578 I can see in every example, that the value for name is always quoted.
Content-Disposition: form-data; name="user"
I did not find any hint if it is mandantory or not to quote the values, so I cannot judge who is wrong here.
To get such quoted name values you only have to quote the values in code.
public static async Task UploadAsync(string url, int job_id, string filename, string filePath) {
try {
// Submit the form using HttpClient and
// create form data as Multipart (enctype="multipart/form-data")
using (var fileStream = new StreamContent(System.IO.File.Open(filePath, FileMode.Open, FileAccess.Read)))
using (var formData = new MultipartFormDataContent()) {
StringContent sJobId = new StringContent(job_id.ToString());
StringContent sOthId = new StringContent(job_id.ToString());
// Try as I might C# adds a CrLf to the end of the job_id tag - so have to strip it in ruby
formData.Add(sOthId, "\"oth_id\"");
formData.Add(sJobId,"\"job_id\"");
fileStream.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
formData.Add(fileStream, "\"dt_file\"", filename);
HttpResponseMessage response = await HttpClient.PostAsync(url, formData);
// If the upload failed there is not a lot we can do
return;
}
} catch (Exception ex) {
// Not a lot we can do here - so just ignore it
System.Diagnostics.Debug.WriteLine($"Upload failed {ex.Message}");
}
}
which will now post this
POST https://example.com/ HTTP/1.1
Host: example.com
Content-Type: multipart/form-data; boundary="c33cdc86-db44-40ef-8e6e-3e13a96218d1"
Content-Length: 528
--c33cdc86-db44-40ef-8e6e-3e13a96218d1
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name="oth_id"
1234
--c33cdc86-db44-40ef-8e6e-3e13a96218d1
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name="job_id"
1234
--c33cdc86-db44-40ef-8e6e-3e13a96218d1
Content-Type: application/octet-stream
Content-Disposition: form-data; name="dt_file"; filename=myfile.txt; filename*=utf-8''myfile.txt
a,b,c,d
aa,"b,b","c
c",dd
aaa
--c33cdc86-db44-40ef-8e6e-3e13a96218d1--
Just found a pull request for PowerShell
// .NET does not enclose field names in quotes, however, modern browsers and curl do.
contentDisposition.Name = $"\"{LanguagePrimitives.ConvertTo<String>(fieldName)}\"";

cURL call in c# bad request

I'm trying to do the following cURL call in a c# .net environment
curl -XPOST -d 'Metadata/Type = "sas"' http://bms.org/bcknd/republish
The C# code is as follows:
var requestContent = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("Metadata/Type", "\"sas\""), });
HttpResponseMessage response = await client.PostAsync("http://bms.org/bcknd/republish", requestContent);
HttpContent responseContent = response.Content;
using (var reader = new StreamReader(await responseContent.ReadAsStreamAsync()))
{
Console.WriteLine(await reader.ReadToEndAsync());
}
I'm getting a 400 Bad request and when I print it out. Maybe it has something to do with the -XPOST and -d parameter from the curl call?
EDIT:
Here's the http request from curl:
POST http://bms.org/bcknd/republish HTTP/1.1
Host: bms.org/bcknd
User-Agent: curl/7.48.0
Accept: */*
Content-Length: 43
Content-Type: application/x-www-form-urlencoded
Metadata/Type = "sas"
Here's the http request from my code:
POST http://bms.org/bcknd/republish HTTP/1.1
Accept: */*
User-Agent: curl/7.48.0
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Host: bms.org/bcknd
Content-Length: 43
Connection: Keep-Alive
Metadata/Type = "sas"
Short Version
Post the data as StringContent without url encoding and check the response status before trying to read the response body. Make sure the call completes before the application exits, otherwise the call will be cancelled when the application exits. That means, use async Task in Main, not async void :
class Program
{
static async Task Main(string[] args)
{
var client=new HttpClient();
var data = new StringContent("Metadata/Type=\"sas\"",Encoding.UTF8,"application/x-www-form-urlencoded");
var response = await client.PostAsync("http://www.google.com/bcknd/republish", data);
if(response.IsSuccessStatusCode)
{
var responseContent = response.Content;
var body=await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}
else
{
Console.WriteLine($"Oops! {response.StatusCode} - {response.ReasonPhrase}");
}
}
}
Explanation
In cases like this it's very important to know what's actually being sent. To do that, one can use a debugging proxy like Fiddler or Charles.
Curl with -d sends unencoded data. This call :
curl -XPOST -d 'Metadata/Type = "sas"' http://bms.org/bcknd/republish
will send :
POST http://www.google.com/bcknd/republish HTTP/1.1
Host: www.google.com
User-Agent: curl/7.55.1
Accept: */*
Connection: Keep-Alive
Content-Length: 21
Content-Type: application/x-www-form-urlencoded
Metadata/Type = "sas"
/ and " would have been replaced with other characters if URL encoding was applied. Note also the User-Agent and Accept headers
If --data-urlencode is used, the value will be URL encoded :
POST http://www.google.com/bcknd/republish HTTP/1.1
Host: www.google.com
User-Agent: curl/7.55.1
Accept: */*
Connection: Keep-Alive
Content-Length: 27
Content-Type: application/x-www-form-urlencoded
Metadata/Type =%20%22sas%22
This code on the other hand :
static async Task Main(string[] args)
{
var client=new HttpClient();
var data = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("Metadata/Type", "\"sas\""), });
var response = await client.PostAsync("http://www.google.com/bcknd/republish", data);
var responseContent = response.Content;
var body=await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}
Will send :
POST http://www.google.com/bcknd/republish HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 25
Host: www.google.com
Metadata%2FType=%22sas%22
To get the original payload, one can use StringContent with hand-coded content:
var data = new StringContent("Metadata/Type= \"sas\"",Encoding.UTF8,"application/x-www-form-urlencoded");
The request is :
POST http://www.google.com/bcknd/republish HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Content-Length: 19
Host: www.google.com
Metadata/Type= "sas"
If you want to send the User-Agent and Accept headers, you can add them to each individual message or as default request headers :
var client=new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("curl","7.55.1"));
These will add :
Accept: */*
User-Agent: curl/7.55.1
to the request
You can call remote URL as following using HttpClient
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), "http://bms.org/bcknd/republish"))
{
request.Content = new StringContent("Metadata/Type = \"sas\"", Encoding.UTF8, "application/x-www-form-urlencoded");
var response = await httpClient.SendAsync(request);
}
}
Here I have just added reference code, by using that you can create your own. I checked your curl request and it seems issue it self.

Formatting of multipart HTTP request body output with restsharp

I am creating a restsharp request in order to trigger a batch direct send push request off to Azure notification hub.
I am receiving a 400 Bad Request response, with the message; Could not find 'notifications' part in the multipart content supplied.
The request looks like such;
const string multipartContentType = "multipart/form-data; boundary=\"simple-boundary\"";
const string authSignature = "myvalidauthsignature";
const string url = "mynotificanhuburl";
const string message = "Some message";
var restClient = new RestClient
{
BaseUrl = new Uri(url),
Proxy = new WebProxy("127.0.0.1", 8888),
};
var request = new RestSharp.RestRequest(Method.POST)
{
RequestFormat = DataFormat.Json,
AlwaysMultipartFormData = true
};
request.AddHeader("Content-Type", multipartContentType);
request.AddHeader("Authorization", authSignature);
request.AddHeader("ServiceBusNotification-Format", "gcm");
request.AddParameter("notification", JsonConvert.SerializeObject(new { data = new { message } }), ParameterType.GetOrPost);
request.AddParameter("devices", JsonConvert.SerializeObject(new List<string> { "123", "456" }), ParameterType.GetOrPost);
var response = restClient.Execute(request);
I can see the raw request via Fiddler;
POST https://xxxxx.servicebus.windows.net/xxx/messages/$batch?direct&api-version=2015-04 HTTP/1.1
Authorization: [redacted]
ServiceBusNotification-Format: gcm
Accept: application/json, application/xml, text/json, text/x-json, text/javascript, text/xml
User-Agent: RestSharp/105.2.3.0
Content-Type: multipart/form-data; boundary=-----------------------------28947758029299
Host: [redacted]
Content-Length: 412
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
-------------------------------28947758029299
Content-Disposition: form-data; name="notification"
{"data":{"message":"Some message"}}
-------------------------------28947758029299
Content-Disposition: form-data; name="devices"
["123","456"]
-------------------------------28947758029299--
Which looks about right. If I copy this into postman with the headers etc, I can see the same error response. HOWEVER in postman when I remove the quote marks around the parameter names, it works and returns a 201 Created response.
So this works....
Content-Disposition: form-data; name=notification
This doesn't
Content-Disposition: form-data; name="notification"
Which seems really peculiar. As we are using restsharp however I don't think I have any direct control over the raw output for the request body. I am wondering;
Is there a restsharp setting to manage these quote, perhaps a formatting setting
Why would the Azure endpoint reject a parameter name with quotes
It is possible that the issue is elsewhere and this is a red herring, but this does seem to be responsible.
Appreciate any help...
According our documentation, request should look like this:
POST https://{Namespace}.servicebus.windows.net/{Notification Hub}/messages/$batch?direct&api-version=2015-08 HTTP/1.1
Content-Type: multipart/mixed; boundary="simple-boundary"
Authorization: SharedAccessSignature sr=https%3a%2f%2f{Namespace}.servicebus.windows.net%2f{Notification Hub}%2fmessages%2f%24batch%3fdirect%26api-version%3d2015-08&sig={Signature}&skn=DefaultFullSharedAccessSignature
ServiceBusNotification-Format: gcm
Host: {Namespace}.servicebus.windows.net
Content-Length: 431
Expect: 100-continue
Connection: Keep-Alive
--simple-boundary
Content-Type: application/json
Content-Disposition: inline; name=notification
{"data":{"message":"Hello via Direct Batch Send!!!"}}
--simple-boundary
Content-Type: application/json
Content-Disposition: inline; name=devices
["Device Token1","Device Token2","Device Token3"]
--simple-boundary--
So, the name parameter's value is not quoted (name=devices). I've not found any RFC which would explicitly specify requirements regarding the situation. However, in examples inside of RFCs a values appear quoted. And because of that I'm going to fix the service to support both options. Fix should come with next deployment in a week or so.
I was plagued by this for a few days and was diligently searching for a solution with RestSharp and was unable to find one as it always default the content type to "multipart/form-data". I know the OP was looking for a way to do this with RestSharp but I don't believe there is currently.My solution comes from a few different posts over a few days so I apologize for not linking to them. Below is a sample Function to perform a multipart/related POST with json body and base64 pdf string as the file.
public static void PostBase64PdfHttpClient(string recordID, string docName, string pdfB64)
{
string url = $"baseURL";
HttpClient client = new HttpClient();
var myBoundary = "------------ThIs_Is_tHe_bouNdaRY_";
string auth = Convert.ToBase64String(Encoding.UTF8.GetBytes($"UN:PW"));
client.DefaultRequestHeaders.Add("Authorization", $"Basic {auth}");
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, $"{url}/api-endpoint");
request.Headers.Date = DateTime.UtcNow;
request.Headers.Add("Accept", "application/json; charset=utf-8");
MultipartContent mpContent = new MultipartContent("related", myBoundary);
mpContent.Headers.TryAddWithoutValidation("Content-Type", $"multipart/related; boundary={myBoundary}");
dynamic jObj = new Newtonsoft.Json.Linq.JObject(); jObj.ID = recordID; jObj.Name = docName;
var jsonSerializeSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
var json = JsonConvert.SerializeObject(jObj, jsonSerializeSettings);
mpContent.Add(new StringContent(json, Encoding.UTF8, "application/json"));
mpContent.Add(new StringContent(pdfB64, Encoding.UTF8, "application/pdf"));
request.Content = mpContent;
HttpResponseMessage response = client.SendAsync(request).Result;
}

HttpClient uploading MultipartFormData to play 2 framework

I have the following code in a Windows Phone 8 project that uses RestSharp client:
public async Task<string> DoMultiPartPostRequest(String ext, JSonWriter jsonObject, ObservableCollection<Attachment> attachments)
{
var client = new RestClient(DefaultUri);
// client.Authenticator = new HttpBasicAuthenticator(username, password);
var request = new RestRequest(ext, Method.POST);
request.RequestFormat = DataFormat.Json;
request.AddParameter("json", jsonObject.ToString(), ParameterType.GetOrPost);
// add files to upload
foreach (var a in attachments)
request.AddFile("attachment", a.FileBody, "attachment.file", a.ContType);
var content = await client.GetResponseAsync(request);
if (content.StatusCode != HttpStatusCode.OK)
return "error";
return content.Content;
}
Fiddler shows the generated header:
POST http://192.168.1.101:9000/rayz/create HTTP/1.1
Content-Type: multipart/form-data; boundary=-----------------------------28947758029299
Content-Length: 71643
Accept-Encoding: identity
Accept: application/json, application/xml, text/json, text/x-json, text/javascript, text/xml
User-Agent: RestSharp 104.1.0.0
Host: 192.168.1.101:9000
Connection: Keep-Alive
Pragma: no-cache
-------------------------------28947758029299
Content-Disposition: form-data; name="json"
{
"userId": "2D73B43390041E868694A85A65E47A09D50F019C180E93BAACC454488F67A411",
"latitude": "35.09",
"longitude": "33.30",
"accuracy": "99",
"maxDistance": "dist",
"Message": "mooohv"
}
-------------------------------28947758029299
Content-Disposition: form-data; name="attachment"; filename="attachment.file"
Content-Type: image/jpeg
?????JFIF??`?`?????C? $" &0P40,,0bFJ:Ptfzxrfpn????????np????????|????????????C"$$0*0^44^?p??????????????????????????????????????????????????????`?"??????????????
-------------------------------28947758029299
The code above works fine on the Play2 API. However since the RestSharp does not seem to be stable I have decided to use the native HttpClient provided by Microsoft.
Hence I wrote another function that uses HttpClient to do the same job:
public async Task<string> DoMultiPartPostRequest2(String ext, JSonWriter jsonObject,
ObservableCollection<Attachment> attachments)
{
var client = new HttpClient();
var content = new MultipartFormDataContent();
var json = new StringContent(jsonObject.ToString());
content.Add(json, "json");
foreach (var a in attachments)
{
var fileContent = new StreamContent(new MemoryStream(a.FileBody));
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "attachment",
FileName = "attachment.file"
};
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse(a.ContType);
content.Add(fileContent);
}
var resp = await client.PostAsync(DefaultUri + ext, content);
if (resp.StatusCode != HttpStatusCode.OK)
return "error";
var reponse = await resp.Content.ReadAsStringAsync();
return reponse;
}
The header that is generated from that code is the following:
POST http://192.168.1.101:9000/rayz/create HTTP/1.1
Accept: */*
Content-Length: 6633
Accept-Encoding: identity
Content-Type: multipart/form-data; boundary="e01b2196-d24a-47a2-a99b-e82cc4a2f92e"
User-Agent: NativeHost
Host: 192.168.1.101:9000
Connection: Keep-Alive
Pragma: no-cache
--e01b2196-d24a-47a2-a99b-e82cc4a2f92e
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=json
{
"userId": "2D73B43390041E868694A85A65E47A09D50F019C180E93BAACC454488F67A411",
"latitude": "35.09",
"longitude": "33.30",
"accuracy": "99",
"maxDistance": "dist",
"Message": "test"
}
--e01b2196-d24a-47a2-a99b-e82cc4a2f92e
Content-Disposition: form-data; name=attachment; filename=attachment.file
Content-Type: image/jpeg
?????JFIF??`?`?????C? $" &0P40,,0bFJ:Ptfzxrfpn????????np????????|????????????C"$$0*0^44^?p????????????????????????????????????????????????????????"??????????????
--e01b2196-d24a-47a2-a99b-e82cc4a2f92e--
So far so good. From my point of view the two headers seem to be identical.
However when I debug the Play 2 API after executing Http.MultipartFormData body = request().body().asMultipartFormData(); I noticed that the multipart data are not being parsed correctly.
More specifically the multipart filed in the body variable is as follows:
MultipartFormData(Map(),List(),List(BadPart(Map(ntent-type -> text/plain; charset=utf-8, content-disposition -> form-data; name=json)), BadPart(Map()), BadPart(Map()), BadPart(Map()), BadPart(Map())),List())
As you can notice it has several (actually 5 in this example) BadParts.
Example: BadPart(Map(ntent-type -> text/plain; charset=utf-8, content-disposition -> form-data; name=json))
Can anyone see what is going wrong here? Is the header generated by HttpClient wrong?
Here is the solution.. (hack)
There seems to be a problem with Play Framework when the boundary has quotes in it.
So i added the following code after multipart is created in order to remove them:
var content = new MultipartFormDataContent();
foreach (var param in content.Headers.ContentType.Parameters.Where(param => param.Name.Equals("boundary")))
param.Value = param.Value.Replace("\"", String.Empty);
Finally i had to add quotes "\"" manually to specific values on the header like the following:
Original: Content-Disposition: form-data; name=attachment; filename=attachment.file
Changed to: Content-Disposition: form-data; name="attachment"; filename="attachment.file"
and
Original: Content-Disposition: form-data; name=json
Changed to: Content-Disposition: form-data; name="json"
I don't think that its a mistake to have quotes or not anywhere in the header and maybe the parsing on play framework should be fixed accordingly.

c# .NET multipart/form-data Upload A File

I want to create an application to automaticly upload a file to googles SearchbyImage-tool
https://www.google.de/searchbyimage/upload
Google is using a multipart/form-data for submitting the file, something like that:
Content-Type: multipart/form-data; boundary=---------------------------265001916915724
Content-Length: 9989
-----------------------------265001916915724
Content-Disposition: form-data; name="image_url"
-----------------------------265001916915724
Content-Disposition: form-data; name="encoded_image"; filename=""
Content-Type: application/octet-stream
-----------------------------265001916915724
Content-Disposition: form-data; name="image_content"
iVBORw0KGgoAAAANSUhEUgAAA7sAAAAdCAYAAABrN3uYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAABovSURBVHhe7V15cF3Vefe00KHT0uk0_7QJk2nS0oLTNNOJaQspGQ-BBuOCgcYuBFLAAlK2sIQtwAcSHDuAbeyCV_C-IxvjRTIuCGN5k42RjLHlRdbmJ1mSV9larOVJv57lnnvPvffc5T0_6Uny92bu2E_vvnPP-c53vvP7vt_3nTcI9CIJkARIAiQBkgBJgCRwEUqgra0NiUQCx48fT_viYmtsbMR3fnAXrr52pPhXXfw9vUgCJAGSAEkgexIYlL1H05NJAiQBkgBJgCRAEiAJ9H8JcGd3MHNyrxn2qPhXXfw9vUgCJAGSAEkgexIYxA00XSQD0gHSAdIB0gHSAdIB0oH0dUB3cjmjq95nD-LRk0kCJAGSAElg0OAf_BczyPKSEUl6T_IgfaD1QPaA7CHtB7QfEh7IBB4gqNmzEqD9mvZr2q9pvw7br4WzKyOQzqZG70kepA-0HpQOkD0ge0D2gOwB2QOpA-nYw5519ah1sk9kn8g-pW-fLob1I5xdiohQRIQYDGIwMsFgkD0he0r7Ce0ntJ-49xOTO_rm-8ehX-OXHscrCxrw_Lv1ePydOoyefAx3TajFbb-pwb-PqcEPn0_g2meOkmdrkEAcfVOyjitn2g8pw4_wzMDBM6405nQilhdDRIAiRhQxSjeiT-uDIs5kP8h-kP1IjxEdKPYzyNldWAjM-6wbswu6MH1jElPyOvHmhx0Yl9uOscva8MLCVjw9pwWPzmrBQ9Oa8E8PfUHOboCzG4VfubPL5R1XzlHt0eeU8WSyT-kGsUifelaffDW76U4URUB6LwKSajRYRYSJcckM46LLf9ySBrw0rwG_mCEj8aPG1-KWsQkMtaLwPBL_vdFFVBNPGSSUQUNnQtCZGBfpmSBRzG6cfUTtJeTt-iUQB3-qfTtqv1ZyJryUGbx0sTHkKqiSahCL9K1n9c1Xs5sqkNfBvJ_BmAkWSHO9CifEiPCOL5bfSeRhVGCNDG-7DgseNLU3w_4sMKI-ocR-xsh-VrOsFlPcaLCKCMeZn-rlLzk1SQ_moZrJeP7oVCIuM7HZmpdIRsueg_ViniPvt-7JdgQs1TWinN2o8Y3dzlRy-8y0asIujAGJsV760fxkWz_o-anYixj7QT-zzzT_NP9ee2xyUJfl7_b9uZv9JZnsRntHN1rOd-FscydOne1E_ekOJI63s4BZToCvexiThgzCoEHsGjIJhzPiEechZ9AQTBKNaf8_PAlDrL_n5VjP5M_VriHyS732Mu1_FQcKsHLxW1j83gTMeedVrFidZ_cnjpyj8VIQ_ozQ_9HrBa7i2DU44yMM3w609cXxh99PiMJL5vlJFa9mfv9JFR96fSjv_vEyx4WGF8fqvZcxZPblUn9-Cv5BhvG-r2aXG-Du7u7Qq72zC03MEJ88l0TiZKcwwOaaCblglz5peezCeSrBa6ER_pnYxiaWO8XhESHHGPgjIotdzq75c-cZmYuoeMbbQ6dcq8UUNxrsXUzOeL39tRR61-ILYCD4_B23DbkTcfXOl3wWn-fMyZ_rTNDzo_Qp_uepgBQFUCJrivjaSJSgMKGtlx7Sn9TXS89G3DI7_5nWJ2qP5of0P9J-XaSMbRxGMeh3dhetLZIQdsFT4uK464XXZhivGubo5m_-MsTZ9TikoW6m7sSG3Rjg7Bq_ErfNnvF_Tfq5YsFEnPnob-xrxsSXoK4dhRvBcWxLGwsotCRx6lwnGlhAQZezH3-68dKo5XWCkLmvRzJWgvBtz-Ob3rf3UXg9rv3tHfwdJZ9U8KEexIpmwLM5vjB_K-789A4-D5ofX80uN8Dc6KoX_39nVzfa2ruZg5vEmSZmFM7IKGP5sfO2ATZ7-F7GKA6DFDeiFRYhkG0EM5JRn6dbYxZnfBfOYOZuLEayO-m62pNJnO_oRFNbJxpbO3GyqQP1Z5nxZgZ8X007_vmWBw2MoaG_VkBibJqnTnJn08y4e-erpyI8cfUn_YieDVLYIsnftBe5-Z9j_qqtmLmkAJPey8e4d1Zj7KTlYvNUACUqAsY3zurlL0L-25sRO2mAwtdLuuthoEWgaTwXlkFA8iP5Xfj-lzrjk337ZXLx5n6wxfXnri6go7Mb59u7cI45YKe5A8awVu2JdlTXt5GzG-Inm_bXuYzNRfca-zpfMxHnPr8Nh5ZeiZ-NHIHSinpsK6lEycE6o5z9GRrp4Nl09T0IH_U8vun99ZUp_NE7-DtKPjo-5CrLfagk86GCgisFO0pFECs6Iyib48sUXs-e_vpqdrkB5pPDU1IKCwvlJHWwCBh3dFlKzfFGZnxPdqCyrg2Hjrqd3UjGaMo-kaZpRzCeLGBMr3pxxpdHeJxXYvXr8l7hgDn3cUfMZvAmOJ_Z91vgXTLKL2FBwmmzcIKbjleOBX-Gc1sJ-DOuEf1h6SbLS-wG7PtZu0tr3e1yRtp-sXEKebj6vk-0q5yLbbuOs9vls-JGiI-983sc_OEVaKuvwqatxVi8ciPmL8-3r-b2Tvv_DczZrT7ZjqL9DcLZjZwfEaGU8pKMqx5xkxHFwu0smmn1-Rrf_PHv6xEgaz63M8bSJRv3eyXT0PYMc3DNsNddc7ttilt_oBjqEP1xjSdmhDYVkKI7u8ERQS5zi9EVDK9M35f3mxhxmQLlH7-eQSEFXr08zw4-8PZEqrR62Qy-FTGc4qxHPid2f43yI8YzKsJLn6cS8SV9In0ZuPpi8tNmr_hU_Llx8v3i6mDpyzqzu_qDOvzv1CN4_rk1eOLxXLzw7GeYN_fLEJfPwMROyrHTi2VqMb9HSznOsVJ7RWqy-nsOu4u_gphdE4sb_LecnCGsD7JNV9qzerZ4lpaGzfphf2Tsl18EJvw0nTG5SOaitX4Wmit-jaa99-PstqHYOP-nWJX3GVYWlOD1xXl4avxcLM0vFgGFI7UOpo3GS6ngI2DbFKXfpoxHNSaFB3UGV2Xc7XPjKLF_W_iA4WCFXzl2E6yz9bLxVVr7v799vb0wfLt0NcP7Wh-C7ZuJsZT42sbbvOSttoDhorD-eBhiFz71y9-Fv0Pwv8KI4Rmpzv4VhQ9bjqzA-U_vROPBZULndu2twPwV-TEyHAMY8AB89toubZ0ofyRFfXGCs6aMAom_bX3g_p3ArmF40oNnXX3XM3pT8zfkHCn_yuxP-Wp2uQFWzC53eMsrqtHalmS1I0mcZM5T3SnmQLEJKqs5j_2VrS7mKrrGQS5kGcHwePhMmaXQIhhAcd-L1vfZ-JhwRc2tqP9U7WsREP737TM8vyMcEaFjNcOqL8JJU9-3nvGyep7luDsRGW-EyvPeGuPV18oahVQZvI6CFWh89UkcHfINNE0YJ5jdzq4k2jrl1cIc3XPnO3G6hQUlznXgGIsKVzAGfv3OOleqeXB_uZK8hPmWs-tm_KTBdWp6o-bPcZqN8-1jgMPa43NgBUnEHBTLAIGYW2-Na2r646pRjlkjoEAKV42fvwv87O0kRv7-LP5j7FHc-EwJrv_5JhxjQQY9Gh_K6PAaHsvBlfJ36nlC10Pg-B2jITc9vT3T-rNqZlSNvKumyCNPe_2lG7FOn1GPiqjS59lnsKIyGOhz0v9oBmPgZQD43TN2KvCS_xN_5ol0nczR5Yxuc6skFTZsOInp046iovIM3p62U_xbXn0C02d9gXHjPjE1x_7mdU6Z86q8xjzu9JqcWN6Ux1Fl9zqOsaFm13u_6E2QszvIasvbZf1-6ej663yD-uUfvml_fWvcM-g-OUU4uueYo9u4dSgObvgpVn-0A6famnGWNVPW2oVFOytw1xNvYHNxghE4rcjduCcWXlJpzPLMFxM-kvuw0Hfr_BN5xoyOP4P2V4WHdDwmiRL3mSj8vcTB4twT6xwUl5Oo8JIL3-h4K2r_19rXxuHLCPPgW4XZrhZn8Dikjpkx1-fUwndCpiV4WcjLCQK4xhvYHzkfwfLX8bfHH_Dgf-lvxMc7Oj5kXKEIYp1n6fKLN3fhodlA7rKlwLF1aFr1TRFcKTlQjdNL5qB5-L8C63NDGF4TAx4Hn3n1LV190edInw8-X3KupH8XpU8Kj8o52jzesveuM4JS8Te0oEhIRqqvZpcbYFmzCxERLCuvslNq6k-3s_TlNpSzCSqtbsWe8mafYXBH2EwRLI3B8tos4dB4IgiuiIv1BT2iJRguE6NoCdT6vsPIehlL9t4TARJPsfriqjnWGWMrIuFiwFyMspeRtvouIizp1Sg0f_gu6u8ehto_-0OceeVl7Cjeh7Ubt9lMLk9hPsMc3RMshbmOMfAJFpg4Ut-OdTtrXcY7uGZXOrtLa1XNrT5_4REZXWacAa7WIz6RDKWXAXdk5a_B1fTDmgOH0TfUBMTWn_g1u2Eg5URjJ-pY5sPRBrZOWJq_d-M0RaDvW83kZaUu88_5eycDwhtRixg_H6-IgKrxeL6vDgUTIlYMsV8fOQMs6uYD5RdfXsRYDVzGKm5GCtV80nqJrkmLn-HU3_TJ5J2-vXCDwFllz94srmZ2Dgpndj_acALvzk4IB5e_Rtz2GirqzuEoe8v__c3vNmHWLAH5Pa-wGtuQz1zsqcXuCic5M8yu66wq4XQrBtlypMXzlSOuDSmwX_6Rm_RhwphH0bTjdlSu-h72zr8Ce979c6z5YC4O1RwHd0I6-Q7InN3tJ7rw5vo9WLhyLUqrWrFofUkIXvIDfmMGllYOpvY_tae68F8EPuE4KhTf-M4oCcELmjMsRxFj_zecgcIZQ4UNnIzLMHyr4YuwDErrwC4XXrDwinOGj59htPvjw-cqQ1Puv0b58wy62Pg_nn0KwoePzAHWsTPprvoF071130aicj8-rijCwwXDsffpHwFLmCc89KoQhtfAgIfhMwPWC8XTesasNRfO_u7NMNT2M87ospeaI5N_Y-NJXZ8MZzjx-2QGRGr-hjrsLQyPDBp8Heu0dfGIizTAMo25YNNnItJ4WtTpdori_Yq68yL6tbeiBbsPNTuGgbUhIjau9qyIQo58xtXXvminyA5mxrSaR5w8zx98nTVI9h3RnriPKa2vfSuiYbXNvyciXuK9FgGx2ldpHWJCvJ9bzxCMbWj_veMZaaeLyAiS53PBkMm-y_Gr9v39c3_uvV--P7elACdu-nsk_vgS1I1_DXqdrqlWt4rV-hyua8fqbTVOTUDo-Lzy1sfjkXfo_LFIC2MnBSNuPy9svtj44uqDVz9Y-2puRYQobf0x6a9XH-R7BVJ4Lbus2d2FBVbN7mStZvdQQts4jetD9dcEhXhE0zCeqPFzOfIor_08bT259NFikI3rRbLyQp6B6y--vHT74rU39N5tf0keJA9aL-b9z48vzPa5L8ovyNlVJy8384OSGKN7kp28vHhxje3o8u_dffdk4eQ2NEE4vJ_sqMJTTy7LsLNrcDYz7ey6nFrO5sZxdk39Mji7hv31V4_fi6dzRuKRe27FgyN_jPtG3IDxM1aglmW_sSNo0NzVgaqzbdhc3YaZW45h2D2_xLKPy2xMG41ndf2Lxkf8VF0f_gzFtwpHMRLItJ_HwgcXuP_78IaWsRcb30bh3ZDPNWdXzofHP7hOzyDU8KoBTxrlz_FpbPwfz97o-LCNlYDyIFZjUxILNnXhyieAlctmozuRC6y5HA98fDPWla3Av8z9OvBvV7L40kqXPxbuj4TgM9f4ZZmcOMPIJz-vPL3v1X7sxe8a_rPmSOJvk_-l4Un9-Qb9sZ1ilz-Xin8QjB9czi6PqChnVx59n0QjS1_mbBVPy6xidbqHGYDfV9mC4sPN2Fna5HJ2RURGc6ZsD99ySGUExXFIeY2rYLSs78jvO8J23sv73O1bER7N2RWnAGvgXdTsav2xGTTrGc7nkjIXEbSw_itGVo3HGq86VMg3XqsGWY3R6b8WoXE9zys___svr7gcX_3JJWj7YjfWbCzEwvc_spndU80d9v95rW55QzsO1LZh5ZaEcHYj58fqrzTIGgNuydSRr1ToqPnjETdnfsPmK157Zv2QfeVzIOcvXf2xMgRizAdfIyaQUn9KZj7wgFBZgmU_6FFiIU_D_HJDYTmnzufSOIgIl2bMxefCsMg1pLfnHr9zyrWdxszvVzUVloFPuNaLpv-W8Rc1KkKepvUXX17u9e0YI6M8Ysif2lPrM9peuO0Z3U_yoPWXDfsR5OzyQ2uK7v2-uE6x0iPO7M6adRRr1h6xvzJ8-G_xoxtexphXcnG4PonXpxTijjsYC-R7pcnsWnW84WnEUSczx6jj5ayu-lkk7eeLVL2u-flBadDuwUu8Em3fFq0sxKbK06hsA_Y3tmPXsXNYd7AFryz7HNcN5-eacJykrgg863qeCd8o51aC9QSvKdScAYk_g_ZXpz3uADj414RvdDwQ8nkm9n_NOZd418F4wfg2Cu8Gfc7b52SRTJE14hFff9z-hcKywfJXzlkc_B-tX4oMMeHD_3yT6UNpNy6_h5UuVC1C_dzLsKpsA4Yu-VsUTbsL3YzMwlWXe_wh3V5bDLnL_wjQH1XjbDvzVkatER-H6Y_j7Lrxv1pvVvqy8Ad0_Q7Dk-p5Un9sf0P4h4ocNK-naH8xeH8Tzq4ewVLObqt1IiD_jbc6BuKrWVrmEVanywH8niPN2HWgCVu_Oudydv0RVTkRzksO0n6eUFTtxVOHvR4975-IAOj3ccYwLCKhRXhcVL5iiP0MrYzu-Ptin1LrjVi42nUYavsAIDEWFZFwt-tjgH2McnAEadcbb6DsL_4UDUcTxhrdo8zJ5XW6ZSx9-eCxNuyvcZzdlOfHxYAbIj6R82cdDpZgv6PLZOHIxjR_Zln59UGLMBnmlo_R_l0yaw7i6U98RomvEQ5SWlk0Pn_Tl3hfMLtb2GnMn9qnMR9gaf5flbdErA8pE1ET4mLcrYwB1X_1u9NcjdhhX3YGQ8D4ZY2MfPEDqpyMB-2wNutnjuR6lOtBFvnLl71JBK6_-PLqz4xMnIwLGl-8iHdfZNxofilDozfWr98xhSAW-B5y8Eg19h6oYgfVVGJLcSUmTz4imN3WdqCFMZC1rLj0i9JT7ORgfnpwPUrrgeG3TPM06f2dXa_z6X5vHxRlPKBK1fpmOo1Z72MOchSzK0biPjjLfECVVoPsGX0qGTFj5uXhk9p2fFLTjbUV7Xjr4wrc-fgk_HbMA54MvFQy8qLwkXLCgjIAw_CtzIhUQXE3vonImHPh6XT2f9m-jg0cBi8uvjXgbRfe8f_ObvXymfbhR3x9qvroUdZ4zP3xMMQufBoifzuDNAr_x8s40fEhP1WdB7H4qeossRXLtnTgsjvq0X1gHEqnXor_2ToCxcd34MYP_w4duQtR_9eXGTJkIzJCjf6RPtfF4ictFRHo4EHp6Ie_V_uD15fj2FLNkcSvTg17GJ40ZUAouev-YdR64lg4wF8M8KeEs6tHxNREeQ3wx0XlWLflCFZtKhOpHuqy6xuIkQmJyMSLCMWNOBdMmY5k42kcLC_H_rJyFB-oRNFXldi8pwqf7q5CflEC63Yk8MHWhGB1FbMbt_04EdKLmSEJAimmNZL19eGKKBMjGJcBuJj1m9Z_Zu01yZPkGeTsuplEySjOnVOKLTtrwM4DFY4uv8oakuLiju6SvMO4847JpiYv2r-laq8ffnUBxi4qwnMzP8Wtj03FxBduxukDE7D4HVMGXKb1VzGWfWU_NjGGUYxetjJEvIxfPEY_Vf24kPtN-LDkQC2-_iAw_v1WXHpLKbq_eBj7pl6C0dtuxidH1-D6ed9Cx3tTUPqNS2NlKFxI_3p-PwrTp-zNl7Fm12SAo_5GEfLeiZAn_-prOPLNP8ADN9zuSbnR02_M_--NCHYqEdb-2h9uzKLWg_fzbK0Pwaa7aniJkSWGMV6Eur-uT5pfmt9s2dug_S8VL3T27L2YNuNz4fByR7fqFEu5TSSxu6IDm_aexsOPrcDUqetSaXLA33uh833b7cNRNPMfcPrg77Bk2ugIhvcC15dVuiROcfZkdGXnfVhNbVANZ-_gXb88-lp__HjKhA-nzVuFy0Y247FZCVzy433C0eXXTz67BksOzcD1c76F1gm_wr4rLgmp2e0r-hKl_1E12lHf75nPfTW7fTtikOkIW_9rr_qRe7H8ppusmtr-13_Sr56OiLp_V1oc-e-qie_p51P7lEHRVxgLso9kb_uGPUrV25w7ZyfGv16I1XmVWLryIKbNK8acBV_iIfZ7u2PHsJ8uoZdLApnI2Bkx4lZ2puZ38OxDN_YMvrJP_fWfuZGJ_qfP2IXV1HprgLO9nvpaf-LL44-GVwpHl19qvodtGIzpe8fj-2__pXB0dWc3_fnM9v4bVaOdnf75anYvNEJG389WxIsYO2J0eiYiRgxff4mo0vzT_kP7T1-0V-n4pjOmb8Hzz32AUaMW4PbbZ-P-_56OSRPXptPUgP9OphjR5559BgX5S_sI40r2fKDb86Ervo1hK_4R3534tQHA6PZtffXV7GY3wpQdj7__RlBIXqSv2auBIAaT1h-tP1p_tH9GZxBsKdoz4B3ObA1w--79nl_RiJ4PyniIz0jS-iZ9GgjrxVezm6kI2UCPyND4iEHoiwwCrV_KcKAMh74dYab5ufjmJ-fJcSivqsmWPzhgn1vfcAq__PXUnq2xtcqAaL-nDCfCV_0XXzFndxQzFPKSERx6T_IgfaD1QPaA7CHtB7QfEh4gPEB4gPAA4QHCA_0bDwhnV0asnE2N3pM8SB9oPSgdIHtA9oDsAdkDsgdSB8gekj0ke0j2kOxh_7KHwtmliEX_jljQ_NH8EQNFDBQxUMRA0X5OeIbwAOEBwgOEBwgPuPGAK42ZIpYUsaSIJUUsKWLZvyKWNF80X8Q4EuNK-I3wG-E3wm-EB8x4gGp2qUaZarapZp1q9inDhTJ86MwKOrOD8ADhAcIDhAcIDww4PEA1u1SDQzVIVLNONft0ZoGtA8QQEUNEDBExRMQQUcYIZYxQxshAwQP_D1qk899cHOG9AAAAAElFTkSuQmCC
-----------------------------265001916915724
Content-Disposition: form-data; name="filename"
filename.bmp
-----------------------------265001916915724
Content-Disposition: form-data; name="num"
10
-----------------------------265001916915724
Content-Disposition: form-data; name="hl"
de
-----------------------------265001916915724
Content-Disposition: form-data; name="bih"
976
-----------------------------265001916915724
Content-Disposition: form-data; name="biw"
1920
-----------------------------265001916915724--
I have absolutely no idea on how to do that in C#... Any suggestions?
using c# you can use HttpClient to do the Post Multi-part Form Data.
below is the code snippet that i tried and worked for me..
give it a try!!
using (var client = new HttpClient())
{
//client.DefaultRequestHeaders.Add("User-Agent", "CBS Brightcove API Service");
string authorization = GenerateBase64();
client.DefaultRequestHeaders.Add("Authorization", authorization);
using (var content = new MultipartFormDataContent())
{
string fileName = Path.GetFileName(textBox1.Text);
//Content-Disposition: form-data; name="json"
var stringContent = new StringContent(InstancePropertyObject);
stringContent.Headers.Remove("Content-Type");
stringContent.Headers.Add("Content-Type", "application/json");
stringContent.Headers.Add("Content-Disposition", "form-data; name=\"instance\"");
content.Add(stringContent, "instance");
var fileContent = new ByteArrayContent(filecontent);
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = fileName
};
content.Add(fileContent);
var result = client.PostAsync(targetURL, content).Result;
Console.Read();
}
}
You could use WebClient's upload file method. You could use headers property to assign packet's headers. A few caveats with WebClient are: setting timeout, unzipping gzipped responses and finally if you intend to make multiple simultaneous requests removing connections limit

Categories

Resources