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

时间:2010-10-08 13:06:35

标签: c# httpwebrequest http-post

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

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抱怨

<links>
    <error id="parameter_missing">Sorry, but we've detected that unexpected data is received. Required parameter 'fileupload' is missing or your post is not multipart/form-data</error>
</links>

FileUpload存在且我使用的multipart/form-data错了吗?

更新:

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

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

更新2

我看了另一个问题Multipart forms from C# client。修改了我的代码与边界,删除了期望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();
}

3 个答案:

答案 0 :(得分:11)

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

  

内容类型: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等工具来了解这些请求是如何构建的。

答案 1 :(得分:11)

我终于通过以下代码获得了它......

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中声明的边界}开始,并且结束边界必须以&amp; amp;以--结束。在我的情况下,我最初使用

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;

一切正常

答案 2 :(得分:0)

这与multipart / form-data

完全不同
  1. 字段之间没有边界(即使只有一个字段也需要)。
  2. 为什么你是base-64编码?
  3. 没有任何迹象表明图像的内容类型。
  4. 查看RFC 2388的实际格式规范。从网页上查看文件上传的Fiddler抓取也很有用。