尝试使用 php 和 curl 复制 Web 请求(图像上传)

Posted

技术标签:

【中文标题】尝试使用 php 和 curl 复制 Web 请求(图像上传)【英文标题】:Trying to replicate web request (image upload) using php and curl 【发布时间】:2015-03-20 12:12:53 【问题描述】:

我正在尝试将图像上传复制到网站,但该网站没有为此提供 api 功能。我设法使用 Charles Proxy 获取请求信息:

这是我的 php 代码:

$post_data = array(
    'photo' => '@'.$filename,
    '_csrftoken' => '5ebcec201972ab6304a33d418129cd13',
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://example.com/api/v1/upload/photo/');
curl_setopt($ch, CURLOPT_USERAGENT, $agent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Host: example.com'
));
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_COOKIEFILE, 'C:/xampp/htdocs/example/cookies.txt');            


$response = curl_exec($ch);
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

print_r($response);

echo $http;

这会返回一个 http 代码为 500 的响应。

【问题讨论】:

【参考方案1】:

您的发帖不正确。

您不需要 Charles Proxy

在上传之前(chrome、firefox),

右键选择检查元素 选择网络标签 刷新页面 选择文档 (chrome) 或 html (firefox) 清空列表 发布您的上传 在请求列表中选择上传请求 在 fireFox 中选择“编辑并重新发送” 在 Chrome 中选择“查看源代码”

在右侧,它将显示请求和响应标头

您需要使您的请求看起来与请求标头完全相同

您必须注意重定向期间添加的重定向(例如 302)和 Cookie。

您将希望查看请求和响应标头,以防它无法查看问题所在。

curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_FAILONERROR,true);

您可能想要获取您的 cookie。创建另一个 curl 请求以获取上传页面。

要捕获 cookie: 为上传页面做 curl 请求 获取响应头($head)

$data = curl_exec($ch);

if (curl_errno($ch))
    $data .= 'Retreive Base Page Error: ' . curl_error($ch);

else 
  $skip = intval(curl_getinfo($ch, CURLINFO_HEADER_SIZE)); 
  $head = substr($data,0,$skip);
  $e = 0;
  while(true)
    $s = strpos($head,'Set-Cookie: ',$e);
    if (!$s)break;
    $s += 12;
    $e = strpos($head,';',$s);
    $cookie = substr($head,$s,$e-$s) ;
    $s = strpos($cookie,'=');
    $key = substr($cookie,0,$s);
    $value = substr($cookie,$s);
    $cookies[$key] = $value;

  

为上传请求格式化捕获的内容:

 $cookie = '';
 $show = '';
 $head = '';
 $delim = '';
 foreach ($cookies as $k => $v)
   $cookie .= "$delim$k$v";
   $delim = '; ';
 

您需要为 curl 添加一些选项

创建 POST 数据字符串

$post = 'key1=value1&key2=value2&key3=value3';

curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

创建一个数组来放置请求标头键值 使用您上传的请求标头中的确切内容填写请求数组。示例:

$request = array();
$request[] = "Host: www.example.com";
$request[] = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
$request[] = "User-Agent: MOT-V9mm/00.62 UP.Browser/6.2.3.4.c.1.123 (GUI) MMP/2.0";
$request[] = "Accept-Language: en-US,en;q=0.5";
$request[] = "Connection: keep-alive";
$request[] = "Cache-Control: no-cache";
$request[] = "Pragma: no-cache";

添加到卷曲:

curl_setopt($ch, CURLOPT_HTTPHEADER, $request);

将跟随设置为假。如果有重定向,您可以看到正在发生的事情。然后创建另一个指向重定向位置的 curl 请求。

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);

上传curl请求Request获取Headers后:

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_ENCODING,"");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_FILETIME, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_TIMEOUT,10);
curl_setopt($ch, CURLOPT_FAILONERROR,true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $request);
$data = curl_exec($ch);
if (curl_errno($ch))
    $data .= 'Retreive Base Page Error: ' . curl_error($ch);

else 
  $skip = intval(curl_getinfo($ch, CURLINFO_HEADER_SIZE)); 
  $head = substr($data,0,$skip);
  $data = substr($data,$skip);
  $info = curl_getinfo($ch);
  $info = var_export($info,true);

echo $head;
echo $info;

如果无法正常工作,请检查 $info 中请求标头的差异。

【讨论】:

对,问题是我无法准确复制请求...我更接近但我不知道问题是什么... 通过使用$request 数组,您应该能够非常接近。如果您按照浏览器开发工具 (FireFox Inspector) 中所示复制浏览器请求,则站点无法区分 curl 和浏览器。为什么它不起作用的答案应该在$info 我在此链接的帮助下成功复制了它:***.com/questions/18318052/… 很好奇,您是否能够像我建议的那样使用 Chrome 开发工具或 FireFox Inspector 在浏览器中看到请求标头?我不明白你为什么需要额外的信息。您需要知道的一切都应该在请求标头中。

以上是关于尝试使用 php 和 curl 复制 Web 请求(图像上传)的主要内容,如果未能解决你的问题,请参考以下文章

PHP cURL无法向api发送POST请求

使用 PHP curl 发送 xml 请求

检查PHP curl请求是否已超时

php curl模拟post请求提交数据样例总结

PHP CURL DELETE 请求

如何使用curl在php中调试get请求