Enviar un archivo a través de HTTP POST con C #

He estado buscando y leyendo sobre eso y no he podido encontrar nada realmente útil.

Estoy escribiendo una pequeña aplicación para ganar C # que permite al usuario enviar archivos a un servidor web, no por FTP, sino por HTTP usando POST. Piense en ello como un formulario web, pero se ejecuta en una aplicación de Windows.

Tengo mi objeto HttpWebRequest creado usando algo como esto

HttpWebRequest req = WebRequest.Create(uri) as HttpWebRequest 

y también establece las propiedades Method , ContentType y ContentLength . Pero eso es lo lejos que puedo llegar.

Este es mi pedazo de código:

 HttpWebRequest req = WebRequest.Create(uri) as HttpWebRequest; req.KeepAlive = false; req.Method = "POST"; req.Credentials = new NetworkCredential(user.UserName, user.UserPassword); req.PreAuthenticate = true; req.ContentType = file.ContentType; req.ContentLength = file.Length; HttpWebResponse response = null; try { response = req.GetResponse() as HttpWebResponse; } catch (Exception e) { } 

Entonces mi pregunta es básicamente cómo puedo enviar un archivo (archivo de texto, imagen, audio, etc.) con C # a través de HTTP POST.

¡Gracias!

    Usando .NET 4.5 (o .NET 4.0 agregando el paquete Microsoft.Net.Http desde NuGet) hay una manera más fácil de simular solicitudes de formularios. Aquí hay un ejemplo:

     private async Task Upload(string actionUrl, string paramString, Stream paramFileStream, byte [] paramFileBytes) { HttpContent stringContent = new StringContent(paramString); HttpContent fileStreamContent = new StreamContent(paramFileStream); HttpContent bytesContent = new ByteArrayContent(paramFileBytes); using (var client = new HttpClient()) using (var formData = new MultipartFormDataContent()) { formData.Add(stringContent, "param1", "param1"); formData.Add(fileStreamContent, "file1", "file1"); formData.Add(bytesContent, "file2", "file2"); var response = await client.PostAsync(actionUrl, formData); if (!response.IsSuccessStatusCode) { return null; } return await response.Content.ReadAsStreamAsync(); } } 

    Para enviar solo el archivo sin formato:

     using(WebClient client = new WebClient()) { client.UploadFile(address, filePath); } 

    Si desea emular un formulario de navegador con un , entonces eso es más difícil. Vea esta respuesta para una respuesta multipart / form-data.

    Para mí, client.UploadFile todavía client.UploadFile el contenido en una solicitud multiparte, así que tuve que hacerlo así:

     using (WebClient client = new WebClient()) { client.Headers.Add("Content-Type", "application/octet-stream"); using (Stream fileStream = File.OpenRead(filePath)) using (Stream requestStream = client.OpenWrite(new Uri(fileUploadUrl), "POST")) { fileStream.CopyTo(requestStream); } } 

    Tuve el mismo problema y este código siguiente respondió perfectamente a este problema:

     //Identificate separator string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x"); //Encoding byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); //Creation and specification of the request HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url); //sVal is id for the webService wr.ContentType = "multipart/form-data; boundary=" + boundary; wr.Method = "POST"; wr.KeepAlive = true; wr.Credentials = System.Net.CredentialCache.DefaultCredentials; string sAuthorization = "login:password";//AUTHENTIFICATION BEGIN byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(sAuthorization); string returnValue = System.Convert.ToBase64String(toEncodeAsBytes); wr.Headers.Add("Authorization: Basic " + returnValue); //AUTHENTIFICATION END Stream rs = wr.GetRequestStream(); string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}"; //For the POST's format //Writting of the file rs.Write(boundarybytes, 0, boundarybytes.Length); byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(Server.MapPath("questions.pdf")); 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, "file", "questions.pdf", contentType); byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header); rs.Write(headerbytes, 0, headerbytes.Length); FileStream fileStream = new FileStream(Server.MapPath("questions.pdf"), 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(); rs = null; WebResponse wresp = null; try { //Get the response wresp = wr.GetResponse(); Stream stream2 = wresp.GetResponseStream(); StreamReader reader2 = new StreamReader(stream2); string responseData = reader2.ReadToEnd(); } catch (Exception ex) { string s = ex.Message; } finally { if (wresp != null) { wresp.Close(); wresp = null; } wr = null; } 

    Debe escribir su archivo en la secuencia de solicitud:

     using (var reqStream = req.GetRequestStream()) { reqStream.Write( ... ) // write the bytes of the file } 

    Para publicar archivos a partir de matrices de bytes:

     private static string UploadFilesToRemoteUrl(string url, IList files, NameValueCollection nvc) { string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x"); var request = (HttpWebRequest) WebRequest.Create(url); request.ContentType = "multipart/form-data; boundary=" + boundary; request.Method = "POST"; request.KeepAlive = true; var postQueue = new ByteArrayCustomQueue(); var formdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}"; foreach (string key in nvc.Keys) { var formitem = string.Format(formdataTemplate, key, nvc[key]); var formitembytes = Encoding.UTF8.GetBytes(formitem); postQueue.Write(formitembytes); } var headerTemplate = "\r\n--" + boundary + "\r\n" + "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" + "Content-Type: application/zip\r\n\r\n"; var i = 0; foreach (var file in files) { var header = string.Format(headerTemplate, "file" + i, "file" + i + ".zip"); var headerbytes = Encoding.UTF8.GetBytes(header); postQueue.Write(headerbytes); postQueue.Write(file); i++; } postQueue.Write(Encoding.UTF8.GetBytes("\r\n--" + boundary + "--")); request.ContentLength = postQueue.Length; using (var requestStream = request.GetRequestStream()) { postQueue.CopyToStream(requestStream); requestStream.Close(); } var webResponse2 = request.GetResponse(); using (var stream2 = webResponse2.GetResponseStream()) using (var reader2 = new StreamReader(stream2)) { var res = reader2.ReadToEnd(); webResponse2.Close(); return res; } } public class ByteArrayCustomQueue { private LinkedList arrays = new LinkedList(); ///  /// Writes the specified data. ///  /// The data. public void Write(byte[] data) { arrays.AddLast(data); } ///  /// Gets the length. ///  ///  /// The length. ///  public int Length { get { return arrays.Sum(x => x.Length); } } ///  /// Copies to stream. ///  /// The request stream. ///  public void CopyToStream(Stream requestStream) { foreach (var array in arrays) { requestStream.Write(array, 0, array.Length); } } } 
      public string SendFile(string filePath) { WebResponse response = null; try { string sWebAddress = "Https://www.address.com"; string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x"); byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(sWebAddress); wr.ContentType = "multipart/form-data; boundary=" + boundary; wr.Method = "POST"; wr.KeepAlive = true; wr.Credentials = System.Net.CredentialCache.DefaultCredentials; Stream stream = wr.GetRequestStream(); string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}"; stream.Write(boundarybytes, 0, boundarybytes.Length); byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(filePath); stream.Write(formitembytes, 0, formitembytes.Length); 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", Path.GetFileName(filePath), Path.GetExtension(filePath)); byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header); stream.Write(headerbytes, 0, headerbytes.Length); FileStream fileStream = new FileStream(filePath, 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--" + boundary + "--\r\n"); stream.Write(trailer, 0, trailer.Length); stream.Close(); response = wr.GetResponse(); Stream responseStream = response.GetResponseStream(); StreamReader streamReader = new StreamReader(responseStream); string responseData = streamReader.ReadToEnd(); return responseData; } catch (Exception ex) { return ex.Message; } finally { if (response != null) response.Close(); } }