I'm trying to simulate HTTP post file exactly like the browser (chrome) does:
HTML:
<form name="fnup" method="post" action="action.shtml" enctype="multipart/form-data">
<input name="firmfile" id="firmfile" type="file">
<input type="submit" id="firmbutton" value="Upgrade" class="othsave">
</form>
C#:
public async Task<string> UploadFile(string actionUrl, string filePath)
{
var httpClient = new HttpClient();
//Should I need to add all those headers??? it will help me? what is necessary?
httpClient.DefaultRequestHeaders.Add("Upgrade-Insecure-Requests", "1");
httpClient.DefaultRequestHeaders.Add("Origin", "http://" + ip);
httpClient.DefaultRequestHeaders.Add("Upgrade-Insecure-Requests", "1");
httpClient.DefaultRequestHeaders.Add("Pragma", "no-cache");
httpClient.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36");
httpClient.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
httpClient.DefaultRequestHeaders.Add("Referer", "http://" + ip + "/");
httpClient.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate");
httpClient.DefaultRequestHeaders.Add("Accept-Language", "he,en-US;q=0.9,en;q=0.8");
httpClient.DefaultRequestHeaders.Add("Cookie", "page=DevSet");
FileStream paramFileStream = File.OpenRead(filePath);
HttpContent fileStreamContent = new StreamContent(paramFileStream);
using (var content = new MultipartFormDataContent())
{
content.Add(fileStreamContent, "firmfile", Path.GetFileName(filePath));
HttpResponseMessage response = await httpClient.PostAsync(actionUrl, content);
string res = await response.Content.ReadAsStringAsync();
return await Task.Run(() => res);
}
}
The C# example is not working in my server, and I cannot understand why...
After looking on Wireshark, I've seen some differents:
Chrome:
C#
The questions:
1) How can I delete the "filename*=utf-8''VP445_all_V116.bin"
from Content-Disposition
2) Why I cannot see the second line Content-Type: application/octet-stream
like in Chrome?
3) Also the Content-length is not the same (even it's the same file)
4) The bottom line is that the C# is not working and chrome is working, and the server side is black-box for me, so I need to guess here what I'm doing wrong in C# post request.
Found the solution.
The problem indeed was the 'Content-Type: application/octet-stream'
Why the HttpClient
StreamContent
is not added it automatically? I really don't know.
The workaround is added it manually
The main idea is from here: https://github.com/paulcbetts/ModernHttpClient/issues/92
Here is the correct C# code:
public async Task<string> UploadFile(string actionUrl, string filePath)
{
var httpClient = new HttpClient();
httpClient.Timeout = TimeSpan.FromMilliseconds(FileReqTimeout);
FileStream fileStream = File.OpenRead(filePath);
var streamContent = new StreamContent(fileStream);
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
streamContent.Headers.ContentDisposition.Name = "\"firmfile\"";
streamContent.Headers.ContentDisposition.FileName = "\"" + Path.GetFileName(filePath) + "\"";
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
string boundary = Guid.NewGuid().ToString();
var content = new MultipartFormDataContent(boundary);
content.Headers.Remove("Content-Type");
content.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data; boundary=" + boundary);
content.Add(streamContent);
HttpResponseMessage response = null;
try
{
response = await httpClient.PostAsync(actionUrl, content, cts.Token);
}
catch (WebException ex)
{
// handle web exception
return null;
}
catch (TaskCanceledException ex)
{
if (ex.CancellationToken == cts.Token)
{
// a real cancellation, triggered by the caller
return null;
}
else
{
// a web request timeout (possibly other things!?)
return null;
}
}
try
{
response.EnsureSuccessStatusCode();
}
catch (Exception)
{
return null;
};
string res = await response.Content.ReadAsStringAsync();
return await Task.Run(() => res);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With