使用HttpWebRequest使用multipart / form-data POST数据/上传图像

我正在尝试使用ImageShack API上传图像。 要使用它,我应该使用multipart/form-data POST图像。 我这样做……

 var postData = ""; var req = HttpWebRequest.Create("http://www.imageshack.us/upload_api.php"); req.Method = "POST"; req.ContentType = "multipart/form-data"; postData += "key=my_key_here&"; postData += "type=base64&"; // get base64 data from image byte[] bytes = File.ReadAllBytes(@"D:\tmp\WpfApplication1\WpfApplication1\Images\Icon128.gif"); string encoded = Convert.ToBase64String(bytes); postData += "fileupload=" + encoded; byte[] reqData = Encoding.UTF8.GetBytes(postData); using (Stream dataStream = req.GetRequestStream()) { dataStream.Write(reqData, 0, reqData.Length); } var res = (HttpWebResponse)req.GetResponse(); var resStream = res.GetResponseStream(); var reader = new StreamReader(resStream); string resString = reader.ReadToEnd(); txt1.Text = resString; 

但ImageShack抱怨说

  Sorry, but we've detected that unexpected data is received. Required parameter 'fileupload' is missing or your post is not multipart/form-data  

FileUpload存在,我使用multipart/form-data什么错误?

更新:

新代码http://pastebin.com/TN6e0CD8

发布数据http://pastebin.com/fYE9fsxs

更新2

我从C#客户端查看了另一个Multipart表单问题。 用边界修改我的代码,删除了期望100标题仍然让我无法正常工作…

 ServicePointManager.Expect100Continue = false; var boundary = "-----------------------------28520690214962"; var newLine = Environment.NewLine; var propFormat = boundary + newLine + "Content-Disposition: form-data; name=\"{0}\"" + newLine + newLine + "{1}" + newLine + newLine; var fileHeaderFormat = boundary + newLine + "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"" + newLine; var req = (HttpWebRequest)HttpWebRequest.Create("http://jm/php/upload.php"); req.Method = WebRequestMethods.Http.Post; req.ContentType = "multipart/form-data; boundary=" + boundary; using (var reqStream = req.GetRequestStream()) { var reqWriter = new StreamWriter(reqStream); var tmp = string.Format(propFormat, "str1", "hello world"); reqWriter.Write(tmp); tmp = string.Format(propFormat, "str2", "hello world 2"); reqWriter.Write(tmp); reqWriter.Write(boundary + "--"); reqWriter.Flush(); } var res = req.GetResponse(); using (var resStream = res.GetResponseStream()) { var reader = new StreamReader(resStream); txt1.Text = reader.ReadToEnd(); } 

我相信您没有正确构建请求正文。 首先,您需要在内容类型标题中包含部分边界(随机文本)。 例如,

内容类型:multipart / form-data; 边界= —- WebKitFormBoundarySkAQdHysJKel8YBM

现在请求体的格式就像

 ------WebKitFormBoundarySkAQdHysJKel8YBM Content-Disposition: form-data;name="key" KeyValueGoesHere ------WebKitFormBoundarySkAQdHysJKel8YBM Content-Disposition: form-data;name="param2" ValueHere ------WebKitFormBoundarySkAQdHysJKel8YBM Content-Disposition: form-data;name="fileUpload"; filename="y1.jpg" Content-Type: image/jpeg [image data goes here] 

我建议你使用Fiddler这样的工具来理解这些请求是如何构建的。

我终于得到了以下代码……

 var boundary = "------------------------" + DateTime.Now.Ticks; var newLine = Environment.NewLine; var propFormat = "--" + boundary + newLine + "Content-Disposition: form-data; name=\"{0}\"" + newLine + newLine + "{1}" + newLine; var fileHeaderFormat = "--" + boundary + newLine + "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"" + newLine; var req = (HttpWebRequest)HttpWebRequest.Create("http://jm/php/upload.php"); req.Method = WebRequestMethods.Http.Post; req.ContentType = "multipart/form-data; boundary=" + boundary; using (var reqStream = req.GetRequestStream()) { var reqWriter = new StreamWriter(reqStream); var tmp = string.Format(propFormat, "str1", "hello world"); reqWriter.Write(tmp); tmp = string.Format(propFormat, "str2", "hello world 2"); reqWriter.Write(tmp); reqWriter.Write("--" + boundary + "--"); reqWriter.Flush(); } var res = req.GetResponse(); using (var resStream = res.GetResponseStream()) { var reader = new StreamReader(resStream); txt1.Text = reader.ReadToEnd(); } 

注意边界必须以-- {在ContentType中声明的边界}开始,结束边界必须以--开头和结尾。 在我的情况下,我最初使用

 var propFormat = boundary + newLine + "Content-Disposition: form-data; name=\"{0}\"" + newLine + newLine + "{1}" + newLine; 

用它替换它

 var propFormat = "--" + boundary + newLine + "Content-Disposition: form-data; name=\"{0}\"" + newLine + newLine + "{1}" + newLine; 

一切正常

这与multipart / form-data完全不同

  1. 字段之间没有边界(甚至需要一个字段)。
  2. 为什么你的base-64编码?
  3. 没有迹象表明图像的内容类型。

请查看RFC 2388的实际格式规范。 从网页上查看文件上传的Fiddler抓取也很有用。