2014-10-30 28 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; 
    }