2014-10-30 72 views
4

我想通過API以編程方式上傳圖像到另一臺服務器。 API期望我以字節數組的形式上傳圖像,以便在字段中發送:「image_content」。無法使用httpwebrequest在c上傳圖像#

我的實現和調用代碼如下。網絡請求會觸發服務器,但服務器會迴應圖像不在我的網絡請求中。

當我運行下面的代碼時,出現圖像不在請求中的錯誤。我在這裏錯過了什麼?

public static class FormUpload 
{ 
    private static readonly Encoding encoding = Encoding.UTF8; 
    public static HttpWebResponse MultipartFormDataPost(string postUrl, string userAgent, Dictionary<string, object> postParameters) 
    { 
     string formDataBoundary = String.Format("----------{0:N}", Guid.NewGuid()); 
     string contentType = "multipart/form-data; boundary=" + formDataBoundary; 

    byte[] formData = GetMultipartFormData(postParameters, formDataBoundary); 

    return PostForm(postUrl, userAgent, contentType, formData); 
} 
private static HttpWebResponse PostForm(string postUrl, string userAgent, string contentType, byte[] formData) 
{ 
    HttpWebRequest request = WebRequest.Create(postUrl) as HttpWebRequest; 

    if (request == null) 
    { 
     throw new NullReferenceException("request is not a http request"); 
    } 

    // Set up the request properties. 
    request.Method = "POST"; 
    request.ContentType = contentType; 
    request.UserAgent = userAgent; 
    request.ContentLength = formData.Length; 


    // Send the form data to the request. 
    using (Stream requestStream = request.GetRequestStream()) 
    { 
     requestStream.Write(formData, 0, formData.Length); 
     requestStream.Close(); 
    } 

    return request.GetResponse() as HttpWebResponse; 
} 

private static byte[] GetMultipartFormData(Dictionary<string, object> postParameters, string boundary) 
{ 
    Stream formDataStream = new System.IO.MemoryStream(); 
    bool needsCLRF = false; 

    foreach (var param in postParameters) 
    { 
     if (param.Value is FileParameter) 
     { 
      FileParameter fileToUpload = (FileParameter)param.Value; 

      // Add just the first part of this param, since we will write the file data directly to the Stream 
      string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\n\r\n", 
       boundary, 
       param.Key, 
       fileToUpload.FileName ?? param.Key, 
       fileToUpload.ContentType ?? "application/octet-stream"); 

      formDataStream.Write(encoding.GetBytes(header), 0, encoding.GetByteCount(header)); 

      // Write the file data directly to the Stream, rather than serializing it to a string. 
      formDataStream.Write(fileToUpload.File, 0, fileToUpload.File.Length); 
     } 
     else 
     { 
      string postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}", 
       boundary, 
       param.Key, 
       param.Value); 
      formDataStream.Write(encoding.GetBytes(postData), 0, encoding.GetByteCount(postData)); 
     } 
    } 

    // Add the end of the request. Start with a newline 
    string footer = "\r\n--" + boundary + "--\r\n"; 
    formDataStream.Write(encoding.GetBytes(footer), 0, encoding.GetByteCount(footer)); 

    // Dump the Stream into a byte[] 
    formDataStream.Position = 0; 
    byte[] formData = new byte[formDataStream.Length]; 
    formDataStream.Read(formData, 0, formData.Length); 
    formDataStream.Close(); 

    return formData; 
} 

public class FileParameter 
{ 
    public byte[] File { get; set; } 
    public string FileName { get; set; } 
    public string ContentType { get; set; } 
    public FileParameter(byte[] file) : this(file, null) { } 
    public FileParameter(byte[] file, string filename) : this(file, filename, null) { } 
    public FileParameter(byte[] file, string filename, string contenttype) 
    { 
     File = file; 
     FileName = filename; 
     ContentType = contenttype; 
    } 
} 

}

上面的代碼要調用的函數是:

// Read file data 
FileStream fs = new FileStream("c:\\myimage.jpeg", FileMode.Open, FileAccess.Read); 
byte[] data = new byte[fs.Length]; 
fs.Read(data, 0, data.Length); 
fs.Close(); 

// Generate post objects 
Dictionary<string, object> postParameters = new Dictionary<string, object>(); 
postParameters.Add("image_content",data); 

// Create request and receive response 
string postURL = "myurl"; 
string userAgent = "Mozilla"; 
HttpWebResponse webResponse = FormUpload.MultipartFormDataPost(postURL, userAgent, postParameters); 

// Process response 
StreamReader responseReader = new StreamReader(webResponse.GetResponseStream()); 
string fullResponse = responseReader.ReadToEnd(); 
webResponse.Close(); 
Response.Write(fullResponse); 
+1

閱讀本http://stackoverflow.com/questions/1131425/send-a-file-via-http-post-with-c-sharp – 2014-10-30 08:06:01

+0

你嘗試使用WebReq.ContentType =「形象/ JPEG「; ? – Mez 2014-10-30 08:20:28

+0

@Mez,是的。我嘗試過這個。 – 2014-10-30 08:42:40

回答

1

你所有的代碼是好的,但你忘了編碼您參數

試試這個

string postData = string.Format("--{0}\r\nContent-Disposition: 
form-data; name=\"{1}\"\r\n\r\n{2}", 
       boundary, 
       HttpUtility.UrlEncode(param.Key), 
       HttpUtility.UrlEncode(param.Value)); 

如果是binar Y數據

HttpUtility.UrlEncode(Convert.ToBase64String(byte[])) 

嘗試使用此代碼對你的要求

NameValueCollection outgoingQueryString = HttpUtility.ParseQueryString(String.Empty); 
outgoingQueryString.Add("uname", "username"); 
outgoingQueryString.Add("pname", "password"); 
string postdata = outgoingQueryString.ToString(); 

添加參數,並在您請求

3

在我看來,你應該使用MultipartFormDataContent類,因爲它「爲使用multipart/form-data MIME類型編碼的內容提供容器」。試試這個

public static HttpWebResponse MultipartFormDataPost(string postUrl, string userAgent, byte[] data) 
    { 
     string contentType; 
     byte[] formData = Program.GetMultipartFormData(data, out contentType); 
     return PostForm(postUrl, userAgent, contentType, formData); 
    } 

    public static byte[] GetMultipartFormData(byte[] data, out string contentType) 
    { 
     var byteArrayContent = new ByteArrayContent(data); 
     byteArrayContent.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg"); 
     byteArrayContent.Headers.Add("image_content", "myimage.jpeg"); 

     var content = new MultipartFormDataContent(String.Format("----------{0:N}", Guid.NewGuid())) { byteArrayContent }; 
     contentType = content.Headers.ContentType.ToString(); 

     return content.ReadAsByteArrayAsync().Result; 
    }