Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upload files with HTTPWebrequest (multipart/form-data)

Is there any class, library or some piece of code which will help me to upload files with HTTPWebrequest?

Edit 2:

I do not want to upload to a WebDAV folder or something like that. I want to simulate a browser, so just like you upload your avatar to a forum or upload a file via form in a web application. Upload to a form which uses a multipart/form-data.

Edit:

WebClient is not cover my requirements, so I'm looking for a solution with HTTPWebrequest.

like image 761
dr. evil Avatar asked Feb 19 '09 18:02

dr. evil


People also ask

How do you send a file using multipart form data?

Follow this rules when creating a multipart form: Specify enctype="multipart/form-data" attribute on a form tag. Add a name attribute to a single input type="file" tag. DO NOT add a name attribute to any other input, select or textarea tags.


2 Answers

Took the code above and fixed because it throws Internal Server Error 500. There are some problems with \r\n badly positioned and spaces etc. Applied the refactoring with memory stream, writing directly to the request stream. Here is the result:

    public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc) {         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.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);             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;             }         } finally {             wr = null;         }     } 

and sample usage:

    NameValueCollection nvc = new NameValueCollection();     nvc.Add("id", "TTR");     nvc.Add("btn-submit-photo", "Upload");     HttpUploadFile("http://your.server.com/upload",           @"C:\test\test.jpg", "file", "image/jpeg", nvc); 

It could be extended to handle multiple files or just call it multiple times for each file. However it suits your needs.

like image 72
Cristian Romanescu Avatar answered Oct 05 '22 09:10

Cristian Romanescu


I was looking for something like this, Found in : http://bytes.com/groups/net-c/268661-how-upload-file-via-c-code (modified for correctness):

public static string UploadFilesToRemoteUrl(string url, string[] files, NameValueCollection formFields = null) {     string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");      HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);     request.ContentType = "multipart/form-data; boundary=" +                             boundary;     request.Method = "POST";     request.KeepAlive = true;      Stream memStream = new System.IO.MemoryStream();      var boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +                                                             boundary + "\r\n");     var endBoundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +                                                                 boundary + "--");       string formdataTemplate = "\r\n--" + boundary +                                 "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";      if (formFields != null)     {         foreach (string key in formFields.Keys)         {             string formitem = string.Format(formdataTemplate, key, formFields[key]);             byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);             memStream.Write(formitembytes, 0, formitembytes.Length);         }     }      string headerTemplate =         "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" +         "Content-Type: application/octet-stream\r\n\r\n";      for (int i = 0; i < files.Length; i++)     {         memStream.Write(boundarybytes, 0, boundarybytes.Length);         var header = string.Format(headerTemplate, "uplTheFile", files[i]);         var headerbytes = System.Text.Encoding.UTF8.GetBytes(header);          memStream.Write(headerbytes, 0, headerbytes.Length);          using (var fileStream = new FileStream(files[i], FileMode.Open, FileAccess.Read))         {             var buffer = new byte[1024];             var bytesRead = 0;             while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)             {                 memStream.Write(buffer, 0, bytesRead);             }         }     }      memStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);     request.ContentLength = memStream.Length;      using (Stream requestStream = request.GetRequestStream())     {         memStream.Position = 0;         byte[] tempBuffer = new byte[memStream.Length];         memStream.Read(tempBuffer, 0, tempBuffer.Length);         memStream.Close();         requestStream.Write(tempBuffer, 0, tempBuffer.Length);     }      using (var response = request.GetResponse())     {         Stream stream2 = response.GetResponseStream();         StreamReader reader2 = new StreamReader(stream2);         return reader2.ReadToEnd();     } } 
like image 27
dr. evil Avatar answered Oct 05 '22 08:10

dr. evil