所以我正在研究一个小应用程序,该应用程序当前将指定图像从硬盘发送到Google的反向图像搜索并处理响应。问题是我得到的反应不是预期的。我已经尽我所能来复制POST请求的结构,我不能为我的生活弄清楚为什么我没有得到我期望的响应。我得到了200响应代码,但HTML输出是某种谷歌错误(按图搜索不可用。请在几个小时后再试一次)。我已经使用Fiddler来确定请求的结构,从我可以看出,除了缺少Cookie标头之外,从我的应用程序生成的结构几乎完全相同(可能就是这样吗?)。如果是这样,我将如何创建一个cookie并将其插入我的请求?
Here's the request made through Google's upload service.
Here's the request made through my app.
这是我的代码: (注意:我确信它可以更加雄辩和有效地编写(例如使用StringBuilder),并且我已经对它进行了很多硬编码,但它应该足以暂时测试基本功能)< / p>
String^ url = "https://www.google.com/searchbyimage/upload";
HttpWebRequest^ request = (HttpWebRequest^) WebRequest::Create(url);
request->Method = "POST";
request->UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:16.0) Gecko/20100101 Firefox/16.0";
request->Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
request->Headers["Accept-Language"] = "en-US,en;q=0.5";
request->Headers["Accept-Encoding"] = "gzip, deflate";
String^ boundary = "-----------------------------23281168279961";
request->ContentType = "multipart/form-data; boundary=" + boundary;
request->Referer = "https://www.google.com/imghp?hl=en&tab=wi";
String^ header = boundary + "\n";
header += "Content-Disposition: form-data; name=\"image_url\"\n\n\n";
header += boundary + "\n";
header += "Content-Disposition: form-data; name=\"encoded_image\"; filename=\"2010-04-09-ec52529.png\"\n";
header += "Content-Type: image/png\n\n";
String^ footer = "\n" + boundary + "\n";
footer += "Content-Disposition: form-data; name=\"image_content\"\n\n\n";
footer += boundary + "\n";
footer += "Content-Disposition: form-data; name=\"filename\"\n\n\n";
footer += boundary + "\n";
footer += "Content-Disposition: form-data; name=\"num\"\n\n";
footer += "10\n";
footer += boundary + "\n";
footer += "Content-Disposition: form-data; name=\"hl\"\n\n";
footer += "en\n";
footer += boundary + "\n";
footer += "Content-Disposition: form-data; name=\"safe\"\n\n";
footer += "off\n";
footer += boundary + "\n";
footer += "Content-Disposition: form-data; name=\"bih\"\n\n";
footer += "578\n";
footer += boundary + "\n";
footer += "Content-Disposition: form-data; name=\"biw\"\n\n";
footer += "1366\n";
footer += boundary + "--\n";
array<Byte>^ headerData = Encoding::ASCII->GetBytes(header);
array<Byte>^ imageData = File::ReadAllBytes(oldImage);
array<Byte>^ footerData = Encoding::ASCII->GetBytes(footer);
request->ContentLength = headerData->Length + imageData->Length + footerData->Length;
Stream^ reqStream = request->GetRequestStream();
reqStream->Write(headerData, 0, headerData->Length);
reqStream->Write(imageData, 0, imageData->Length);
reqStream->Write(footerData, 0, footerData->Length);
HttpWebResponse^ response = (HttpWebResponse^) request->GetResponse();
StreamReader^ reader = gcnew StreamReader(response->GetResponseStream());
String^ things = reader->ReadToEnd();
答案 0 :(得分:1)
事实证明,Google在处理请求标头时有点挑剔。我遇到了三个问题:
+
替换为-
,/
替换为_
Content-Type
边界参数不得引用Content-Disposition
名称参数如果您使用的是C#,可以使用MultipartFormDataContent
处理这些怪癖的替代品,代码改编自here:
public class MultipartFormDataContentCompat : MultipartContent
{
public MultipartFormDataContentCompat() : base("form-data")
{
FixBoundaryParameter();
}
public MultipartFormDataContentCompat(string boundary) : base("form-data", boundary)
{
FixBoundaryParameter();
}
public override void Add(HttpContent content)
{
base.Add(content);
AddContentDisposition(content, null, null);
}
public void Add(HttpContent content, string name)
{
base.Add(content);
AddContentDisposition(content, name, null);
}
public void Add(HttpContent content, string name, string fileName)
{
base.Add(content);
AddContentDisposition(content, name, fileName);
}
private void AddContentDisposition(HttpContent content, string name, string fileName)
{
var headers = content.Headers;
if (headers.ContentDisposition != null)
return;
headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = QuoteString(name),
FileName = QuoteString(fileName)
};
}
private string QuoteString(string str)
{
return '"' + str + '"';
}
private void FixBoundaryParameter()
{
var boundary = Headers.ContentType.Parameters.Single(p => p.Name == "boundary");
boundary.Value = boundary.Value.Trim('"');
}
}
上传你的图片:
private static string FileToBase64(string imagePath)
{
byte[] content = File.ReadAllBytes(imagePath);
string base64 = Convert.ToBase64String(content).Replace('+', '-').Replace('/', '_');
return base64;
}
public static void UploadImage(string imagePath)
{
using (var client = new HttpClient())
{
var form = new MultipartFormDataContentCompat();
form.Add(new StringContent(FileToBase64(imagePath)), "image_content");
form.Add(new StringContent(Path.GetFileName(imagePath)), "filename");
var response = client.PostAsync("https://images.google.com/searchbyimage/upload", form).Result;
// Do whatever you want with the response
}
}