metodo - Enviar un archivo a través de HTTP POST con C#
metodo post c# (7)
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!
Debe escribir su archivo en la secuencia de solicitud:
using (var reqStream = req.GetRequestStream())
{
reqStream.Write( ... ) // write the bytes of the file
}
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 <input type="file"/>
, 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);
}
}
Para publicar archivos a partir de matrices de bytes:
private static string UploadFilesToRemoteUrl(string url, IList<byte[]> 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<byte[]> arrays = new LinkedList<byte[]>();
/// <summary>
/// Writes the specified data.
/// </summary>
/// <param name="data">The data.</param>
public void Write(byte[] data) {
arrays.AddLast(data);
}
/// <summary>
/// Gets the length.
/// </summary>
/// <value>
/// The length.
/// </value>
public int Length { get { return arrays.Sum(x => x.Length); } }
/// <summary>
/// Copies to stream.
/// </summary>
/// <param name="requestStream">The request stream.</param>
/// <exception cref="System.NotImplementedException"></exception>
public void CopyToStream(Stream requestStream) {
foreach (var array in arrays) {
requestStream.Write(array, 0, array.Length);
}
}
}
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;
}
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<System.IO.Stream> 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();
}
}
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();
}
}