通过HTTP POST发送一个文件与C#

问题描述:

我一直在寻找和阅读,并没有罚款任何真正有用的东西。通过HTTP POST发送一个文件与C#

我正在写一个小的C#win应用程序,允许用户发送文件到web服务器,而不是通过FTP,但通过HTTP使用POST。把它想象成一个Web窗体,但是在Windows应用程序上运行。

我有我的HttpWebRequest使用这样的事情

HttpWebRequest req = WebRequest.Create(uri) as HttpWebRequest 

创建的对象,并设定了MethodContentTypeContentLength性能。但是,我可以走多远。

这是我的一段代码:

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) 
{ 
} 

所以我的问题基本上是我如何通过HTTP POST C#发送FIE(文本文件,图像,音频等)。

谢谢!如果你想模仿浏览器形式的<input type="file"/>,那是很难

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

+0

请检查http://*.com/questions/15738847/sending-files-using-http-post-in-c-sharp/15739707#15739707 – Sudha 2013-04-01 08:13:36

使用.NET 4.5 (或.NET 4.0,通过添加NuGet的Microsoft.Net.Http包),有一种更简单的方法来模拟表单请求。这里有一个例子:

private 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 = client.PostAsync(actionUrl, formData).Result; 
     if (!response.IsSuccessStatusCode) 
     { 
      return null; 
     } 
     return response.Content.ReadAsStreamAsync().Result; 
    } 
} 

要发送的原始文件。有关多部分/表单数据答案,请参阅this answer

+0

(你当然可以添加标题/凭证/等等正常) – 2009-07-15 13:49:40

+1

谢谢,我已经用它简单的东西,我没有工作。现在,正如你所说,我确实需要模拟一个浏览器输入文件,像这样。 – gabitoju 2009-07-15 13:51:45

你需要写文件的请求流:

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

我已经得到了同样的问题,这个下面的代码在这个问题很好回答:

//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; 
} 

要发布文件,从字节数组:

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); 
     } 
    } 
} 

对我来说client.UploadFile还裹着multipart请求的内容,所以我不得不做这样的:

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); 
    } 
} 

 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(); 
       } 
      }