2009-07-15 48 views
65

我一直在尋找和閱讀,並沒有罰款任何真正有用的東西。通過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://stackoverflow.com/questions/15738847/sending-files-using-http-post-in-c-sharp/15739707#15739707 – Sudha 2013-04-01 08:13:36

回答

79

使用.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; 
    } 
} 
41

要發送的原始文件。有關多部分/表單數據答案,請參閱this answer

+0

(你當然可以添加標題/憑證/等等正常) – 2009-07-15 13:49:40

+1

謝謝,我已經用它簡單的東西,我沒有工作。現在,正如你所說,我確實需要模擬一個瀏覽器輸入文件,像這樣。 – gabitoju 2009-07-15 13:51:45

4

你需要寫文件的請求流:

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

我已經得到了同樣的問題,這個下面的代碼在這個問題很好回答:

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

要發佈文件,從字節數組:

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

對我來說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); 
    } 
} 
0
 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(); 
       } 
      }