.NET WebApi - How to receive a file with additional parameters? - c#

Noob question here, i'm trying to send a file with one added string parameter.
My uploader class looks like that:
public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc)
{
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
wr.ContentType = "multipart/form-data; boundary=" + boundary;
wr.Method = "POST";
wr.KeepAlive = true;
wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
Stream rs = wr.GetRequestStream();
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
foreach (string key in nvc.Keys)
{
rs.Write(boundarybytes, 0, boundarybytes.Length);
string formitem = string.Format(formdataTemplate, key, nvc[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
rs.Write(formitembytes, 0, formitembytes.Length);
}
rs.Write(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, paramName, file, contentType);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
rs.Write(buffer, 0, bytesRead);
}
fileStream.Close();
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Close();
WebResponse wresp = null;
try
{
wresp = wr.GetResponse();
Stream stream2 = wresp.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
var result = reader2.ReadToEnd();
}
catch (Exception ex)
{
Program.log.Error(System.Reflection.MethodBase.GetCurrentMethod().Name + " Error occurred while converting file ", ex);
if (wresp != null)
{
wresp.Close();
wresp = null;
}
}
finally
{
wr = null;
}
}
The string parameters are inside the NameValueCollection.
Now how should the other side, the post method, receive it?
*Also, in this cases where i mix a file + string parameters, should the content type be "application/octet-stream"?
Thanks

For your case, you can create a FileUploadViewModel to contain all your properties including IFormFile. Use this as parameter type to your action method. Default model binder should be able to populate everything for you.
Also see if you need a custom model binder - https://learn.microsoft.com/en-us/aspnet/core/mvc/advanced/custom-model-binding?view=aspnetcore-2.1

Related

HttpWebRequest to upload docx file to curl python from c#

This is what i use to call from ubuntu:
curl -X POST http://192.168.XX.XX:XXXX -F 'file[]=#file1.docx' -i
I want to execute this from c#.
Note: I tried other stackoverflow answers/solutions, but i always get :
internal server error : 505
I could call it successfully using following code.
public static string HttpUploadFile(string file)
{
string paramName = "file[]";
string[] result = null;
string url = "http://192.168.XX.XX:XXXX";
string contenttype_xlsx = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
string contenttype_pptx = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
string contenttype_docx = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
string contentType = "";
switch (Path.GetExtension(file))
{
case ".docx":
contentType = contenttype_docx;
break;
case ".pptx":
contentType = contenttype_pptx;
break;
default:
contentType = contenttype_xlsx;
break;
}
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
wr.ContentType = "multipart/form-data; boundary=" + boundary;
wr.Method = "POST";
wr.KeepAlive = true;
wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
Stream rs = wr.GetRequestStream();
rs.Write(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, paramName, Path.GetFileName(file), contentType);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
rs.Write(buffer, 0, bytesRead);
}
fileStream.Close();
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Close();
WebResponse wresp = null;
try
{
wresp = wr.GetResponse();
Stream stream2 = wresp.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2, Encoding.UTF8);
string s = reader2.ReadToEnd();
JObject obj = JObject.Parse(s);
}
catch (Exception ex)
{
if (wresp != null)
{
wresp.Close();
wresp = null;
}
throw new ApplicationException(ex.Message + ex.StackTrace);
}
finally
{
wr = null;
}
return obj.ToString();
}

HttpWebRequest, uploading a file

I hope someone can help me out. I have the following code, which is attempting to upload a file to the server using a HTTPWebRequest. I simply can't get it to work, resulting in the generic "HTTP Error 500 Internal server" error.
I have tried different iterations, splitting out the code into separate methods etc, but this is the simplest form of the code. I have searched high and low but cannot spot what I'm doing wrong!
Any help would be appreciated.
public HttpWebResponse SubmitPOSTRequest(string url, Dictionary<string, object> postData = null, string fileName = "")
{
byte[] boundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + this.FormDataBoundary + "\r\n");
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
wr.ContentType = "multipart/form-data; boundary=" + this.FormDataBoundary;
wr.Method = "POST";
wr.UserAgent = "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)";
wr.CookieContainer = new CookieContainer();
wr.Timeout = 600000;
using (Stream stream = wr.GetRequestStream())
{
if (postData != null)
{
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
// Loop through for non-file form-data.
foreach (string key in postData.Keys)
{
stream.Write(boundaryBytes, 0, boundaryBytes.Length);
string formitem = string.Format(formdataTemplate, key, postData[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
stream.Write(formitembytes, 0, formitembytes.Length);
}
}
if (!string.IsNullOrWhiteSpace(fileName))
{
stream.Write(boundaryBytes, 0, boundaryBytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, "File", fileName, GetContentType(fileName));
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
stream.Write(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
stream.Write(buffer, 0, bytesRead);
}
fileStream.Close();
}
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + this.FormDataBoundary + "--\r\n");
stream.Write(trailer, 0, trailer.Length);;
}
return wr.GetResponse() as HttpWebResponse;
}

Split file in chunks then upload via boundary

I'm trying to upload some files to a server.
My code looks like:
public void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc, string cookie)
{
try
{
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
SetStatus("Making request");
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
wr.ContentType = "multipart/form-data; boundary=" + boundary;
wr.Method = "POST";
wr.Headers["Cookie"] = cookie;
wr.KeepAlive = true;
wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
Stream rs = wr.GetRequestStream();
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
SetStatus("Parsing values");
foreach (string key in nvc.Keys)
{
rs.Write(boundarybytes, 0, boundarybytes.Length);
string formitem = string.Format(formdataTemplate, key, nvc[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
rs.Write(formitembytes, 0, formitembytes.Length);
}
rs.Write(boundarybytes, 0, boundarybytes.Length);
SetStatus("Reading file");
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, paramName, file, contentType);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
rs.Write(buffer, 0, bytesRead);
}
fileStream.Close();
SetStatus("Sending request");
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Close();
HttpWebResponse wresp = null;
wresp = (HttpWebResponse)wr.GetResponse();
if (wresp.StatusCode != HttpStatusCode.OK)
{
throw new Exception("File was not uploaded successfully.");
}
SetStatus("Success");
}
catch
{
statusLabel.ForeColor = Color.Red;
SetStatus("Failure");
}
}
An call it in this way:
void uploader_DoWork2(object sender, DoWorkEventArgs e)
{
NameValueCollection c = new NameValueCollection();
c.Add("chunk", "0");
c.Add("name", Path.GetFileName(filenameBox.Text));
c.Add("chunks", "1");
HttpUploadFile("https://site.com/upload.php", filenameBox.Text, "file", GetContentType(filenameBox.Text), c, loginCookies);
}
The script works fine and files are uploaded if these are < 2MB. If the file is larger than 2MB it return success even if the file was not successfully uploaded. I think the files larger than 2MB should be splited in chunks and then send to server. But I have no idea how to split file then send to server in chunks...

Send file+parameters in post request

I'm using this code to send parameters to a webpage and getting correct response from it.
System.Net.WebClient oWeb = new System.Net.WebClient();
oWeb.Proxy = System.Net.WebRequest.DefaultWebProxy;
oWeb.Proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
oWeb.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
byte[] bytArguments = System.Text.Encoding.ASCII.GetBytes("value1=123&value2=xyz");
byte[] bytRetData = oWeb.UploadData("http://website.com/file.php", "POST", bytArguments);
response = System.Text.Encoding.ASCII.GetString(bytRetData);
But now I want to send a file like (.doc) to it + above parameters(value1, value2), but I don't know how to do that.
Use WebClient.QueryString to pass name/value pairs associated with the request.
NameValueCollection parameters = new NameValueCollection();
parameters.Add("value1", "123");
parameters.Add("value2", "xyz");
oWeb.QueryString = parameters;
var responseBytes = oWeb.UploadFile("http://website.com/file.php", "path to file");
string response = Encoding.ASCII.GetString(responseBytes);
public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc)
{
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
wr.ContentType = "multipart/form-data; boundary=" + boundary;
wr.Method = "POST";
wr.KeepAlive = true;
wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
Stream rs = wr.GetRequestStream();
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
foreach (string key in nvc.Keys)
{
rs.Write(boundarybytes, 0, boundarybytes.Length);
string formitem = string.Format(formdataTemplate, key, nvc[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
rs.Write(formitembytes, 0, formitembytes.Length);
}
rs.Write(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, paramName, file, contentType);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
rs.Write(buffer, 0, bytesRead);
}
fileStream.Close();
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Close();
WebResponse wresp = null;
try
{
wresp = wr.GetResponse();
Stream stream2 = wresp.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
result = reader2.ReadToEnd();
}
catch (Exception ex)
{
System.Windows.MessageBox.Show("Error occurred while converting file", "Error!");
if (wresp != null)
{
wresp.Close();
wresp = null;
}
}
finally
{
wr = null;
}
}
Copied from SO but can't remember it's link. And this is how it will be used
NameValueCollection nvc = new NameValueCollection();
nvc.Add("parm1", "value1");
nvc.Add("parm2", "value2");
nvc.Add("parm3", "value3");
HttpUploadFile("http://www.example.com/upload.php",#filepath, "file", "text/html", nvc);
Here #filepath is the path of your file you want to upload: c:\file_to_upload.doc
And file is the name of the filed used in php as $_Files['file']

corrupted file name when uploading non-latin file name using HttpWebRequest

I am using HttpWebRequest to upload files to an HttpServlet running on tomcat, if the file name contains non-Latin characters the uploaded file on the server has corrupted characters.
this is my file upload method:
public static void HttpUploadFileEx(string url, string file, string paramName, string contentType, NameValueCollection nvc, WebHeaderCollection collection, NetworkCredential networkCredential)
{
log.Debug(string.Format("Uploading {0} to {1}", file, url));
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
wr.ContentType = "multipart/form-data; boundary=" + boundary;
wr.Method = "POST";
wr.KeepAlive = true;
wr.UseDefaultCredentials = false;
wr.Credentials = networkCredential;
wr.Timeout = Timeout.Infinite;
foreach (string s in collection)
{
wr.Headers[s] = collection[s];
}
Stream rs = wr.GetRequestStream();
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
foreach (string key in nvc.Keys)
{
rs.Write(boundarybytes, 0, boundarybytes.Length);
string formitem = string.Format(formdataTemplate, key, nvc[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
rs.Write(formitembytes, 0, formitembytes.Length);
}
rs.Write(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, paramName, Path.GetFileName(file), contentType);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
rs.Write(buffer, 0, bytesRead);
}
fileStream.Close();
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Close();
WebResponse wresp = null;
try
{
wresp = wr.GetResponse();
Stream stream2 = wresp.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
log.Debug(string.Format("File uploaded, server response is: {0}", reader2.ReadToEnd()));
}
catch (Exception ex)
{
log.Error("Error uploading file", ex);
if (wresp != null)
{
wresp.Close();
wresp = null;
}
}
}
What do I need to change to support non-Latin file names ?
Solved by changing:
wr.ContentType = "multipart/form-data; boundary=" + boundary;
to
wr.ContentType = "multipart/form-data; charset=UTF-8; boundary=" + boundary;

Categories