C# - 发送 HttpWebRequest 远程上传图像?
几天来,我一直在尝试编写一个程序,将图像远程上传到图像主机(imgur.com)。我使用 Wireshark 嗅探浏览器发送的 http 请求,然后创建具有类似标头和参数的 HttpWebRequest。但服务器总是给我发回一些奇怪的东西。请看代码(此代码已简化):
static void Main(string[] args)
{
ServicePointManager.Expect100Continue = false;
CookieContainer cc = new CookieContainer();
List<string> formData = new List<string>();
//The first request - login
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://imgur.com/signin");
configRequest(request, cc);
//add POST params
add(formData, "username", "abcdefgh"); //this is a working account,
add(formData, "password", "abcdefgh"); //feel free to use it if you
add(formData, "remember", "remember"); //want to test
add(formData, "submit", "");
writeToRequestStream(request, formData);
//send request
request.GetResponse();
//The second request - remote upload image
request = (HttpWebRequest)WebRequest.Create("http://imgur.com/upload?sid_hash=9efff36179fef47dc5e078a4575fd96a");
configRequest(request, cc);
//add POST params
formData = new List<string>();
add(formData, "url", "http://img34.imageshack.us/img34/8425/89948070152259768406.jpg");
add(formData, "create_album", "0");
add(formData, "album_title", "Optional Album Title");
add(formData, "album_layout", "b");
add(formData, "edit_url", "0");
writeToRequestStream(request, formData);
//send request
Stream s = request.GetResponse().GetResponseStream();
StreamReader sr = new StreamReader(s);
string html = sr.ReadToEnd();
sr.Close();s.Close();
Console.WriteLine(html + "\n\n");
}
static void add(List<string> formData, string key, string value)
{
formData.Add(HttpUtility.UrlEncode(key) + "=" + HttpUtility.UrlEncode(value));
}
static void configRequest(HttpWebRequest request, CookieContainer cc)
{
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
request.CookieContainer = cc;
request.Credentials = CredentialCache.DefaultCredentials;
request.Accept = "*/*";
request.KeepAlive = true;
request.Referer = "http://imgur.com/";
request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15";
request.Headers.Add("Accept-Language", "en-us,en;q=0.5");
request.Headers.Add("Accept-Encoding", "gzip,deflate");
request.Headers.Add("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
request.Headers.Add("Keep-Alive", "115");
request.Headers.Add("X-Requested-With", "XMLHttpRequest");
request.Headers.Add("Pragma", "no-cache");
request.Headers.Add("Cache-Control", "no-cache");
}
static void writeToRequestStream(HttpWebRequest request, List<string> formData)
{
//build request stream
string queryString = String.Join("&", formData.ToArray());
byte[] byteArray = Encoding.UTF8.GetBytes(queryString);
//write to stream
request.ContentLength = byteArray.Length;
Stream rs = request.GetRequestStream();
rs.Write(byteArray, 0, byteArray.Length);
rs.Close();
}
现在我嗅探我的上传请求(第二个请求)并将其与浏览器的请求进行比较,只有 2 个差异:
浏览器的 'Connection' header ='keep-alive ' 但我的不存在(我不知道为什么,尽管 request.Keep-alive 设置为 'true')
某些浏览器的 cookie 没有出现在我的浏览器中。
响应应该是 JSON,如下所示:
{"hashes":"[\"QcvII\"]","hash":"QcvII","album":false,"edit":false}
但是服务器通过一堆特殊字符响应我的请求...我无法找出上述 2 个差异中的哪一个导致我的代码不起作用。如果您能帮助我使这段代码正常工作,我将非常感激。我是一个新手,所以如果我的代码或我的表达很愚蠢,请不要责怪我。
有人可以帮助使这段代码工作吗?
P/S:我正在使用.net框架4
For several days I've tried to write a program that remote upload image to an image host (imgur.com). I used Wireshark to sniff http requests sent by browser, then create HttpWebRequest with similar headers and parameters. But the server always send back to me something weird. Please look at the code (this code is simplified):
static void Main(string[] args)
{
ServicePointManager.Expect100Continue = false;
CookieContainer cc = new CookieContainer();
List<string> formData = new List<string>();
//The first request - login
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://imgur.com/signin");
configRequest(request, cc);
//add POST params
add(formData, "username", "abcdefgh"); //this is a working account,
add(formData, "password", "abcdefgh"); //feel free to use it if you
add(formData, "remember", "remember"); //want to test
add(formData, "submit", "");
writeToRequestStream(request, formData);
//send request
request.GetResponse();
//The second request - remote upload image
request = (HttpWebRequest)WebRequest.Create("http://imgur.com/upload?sid_hash=9efff36179fef47dc5e078a4575fd96a");
configRequest(request, cc);
//add POST params
formData = new List<string>();
add(formData, "url", "http://img34.imageshack.us/img34/8425/89948070152259768406.jpg");
add(formData, "create_album", "0");
add(formData, "album_title", "Optional Album Title");
add(formData, "album_layout", "b");
add(formData, "edit_url", "0");
writeToRequestStream(request, formData);
//send request
Stream s = request.GetResponse().GetResponseStream();
StreamReader sr = new StreamReader(s);
string html = sr.ReadToEnd();
sr.Close();s.Close();
Console.WriteLine(html + "\n\n");
}
static void add(List<string> formData, string key, string value)
{
formData.Add(HttpUtility.UrlEncode(key) + "=" + HttpUtility.UrlEncode(value));
}
static void configRequest(HttpWebRequest request, CookieContainer cc)
{
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
request.CookieContainer = cc;
request.Credentials = CredentialCache.DefaultCredentials;
request.Accept = "*/*";
request.KeepAlive = true;
request.Referer = "http://imgur.com/";
request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15";
request.Headers.Add("Accept-Language", "en-us,en;q=0.5");
request.Headers.Add("Accept-Encoding", "gzip,deflate");
request.Headers.Add("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
request.Headers.Add("Keep-Alive", "115");
request.Headers.Add("X-Requested-With", "XMLHttpRequest");
request.Headers.Add("Pragma", "no-cache");
request.Headers.Add("Cache-Control", "no-cache");
}
static void writeToRequestStream(HttpWebRequest request, List<string> formData)
{
//build request stream
string queryString = String.Join("&", formData.ToArray());
byte[] byteArray = Encoding.UTF8.GetBytes(queryString);
//write to stream
request.ContentLength = byteArray.Length;
Stream rs = request.GetRequestStream();
rs.Write(byteArray, 0, byteArray.Length);
rs.Close();
}
Now I sniff my uploading request (2nd request) and compare it to the browser's request, there're only 2 differences:
Browser's 'Connection' header ='keep-alive' but mine doesn't exist (I don' know why although request.Keep-alive is set to 'true')
Some browser's cookies doesn't appear in mine.
The response should be a JSON, something like this:
{"hashes":"[\"QcvII\"]","hash":"QcvII","album":false,"edit":false}
But the server responses to my request by a pile of special characters... I can't find out which in above 2 differences makes my code doesn't work. I will extremely appreciate if you can help me making this code work. I'm a newbie so please don't blame me if my code or my expression's silly.
Can anybody help to make this code work?
P/S: i'm using .net framework 4
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我的猜测是,您尝试上传图像时的 sid_hash url 参数是一个会话 ID,需要在登录时更改。
My guess is that the sid_hash url parameter in your attempt to upload the image is a session id that needs to change when you log in.
好的,现在我已经找到了解决方案,幸运的是。忘记我的函数 configRequest() 中的所有内容(除了第一行 3 行),它们只会让事情出错。解决方案是,在发送登录请求后,向主页发送另一个请求(不需要参数,但请记住包含从第一个请求收到的 cookie)。 sid_hash 可以在返回的 HTML 中找到。使用该 sid_hash 发出远程上传请求。
谢谢大家,伙计们。
OK, now I've found out the solution, fortunately. Forget all things in my function configRequest() (except 3 first lines), they just make things go wrong. The solution is, after sending the login request, send another request to the homepage (no parameter needed, but remember to include the cookies received from the 1st request). The sid_hash can be found in the returned HTML. Use that sid_hash to make the remote uploading request.
Thank you all, guys.
不确定您的代码,但 ClipUpload 是一个开源项目,似乎已经满足您的要求:
Not sure about your code, but ClipUpload is an open source project that seems to already do about what you want:
第二个请求很可能包含会话 ID cookie。如果没有这些 cookie,服务器将无法识别您,因此上传将无法进行。
您可以自己设置保持活动状态,但我的建议是将响应标头的片段发布到第一个请求,以便我们可以提供帮助。
更新
根据您的更新,您需要包含此 cookie:
显然该值会随着每次日志记录而变化。
Most likely, the second request contains the session ID cookies. Without those cookies, server will not be able to recognise you hence upload will not work.
You can set the keep-alive yourself but my suggestion is to post snippet of the response headers to the first request so we could help.
UPDATE
According to your updates, you need to include this cookie:
Obviously the value will change with each logging.