Попытка воспроизвести веб-запрос (загрузку изображения) с помощью php и curl

Я пытаюсь воспроизвести загрузку изображения на веб-сайт, но этот веб-сайт не предоставляет для этого функцию API. Мне удалось получить информацию о запросе с помощью Charles Proxy:

Скриншот 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.


person Th3lmuu90    schedule 20.03.2015    source источник


Ответы (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);

Установите значение false. Если есть перенаправление, вы можете видеть, что происходит. затем создайте еще один запрос curl для перенаправления.

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);

После запроса запроса на загрузку curl получите заголовки:

$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.

person Misunderstood    schedule 20.03.2015
comment
Да, проблема в том, что я не могу точно воспроизвести запрос... Я ближе, но я не знаю, в чем проблема... - person Th3lmuu90; 20.03.2015
comment
Используя массив $request, вы сможете подобраться очень близко. Если вы воспроизведете запрос браузера, как показано в инструментах разработки браузера (FireFox Inspector), сайт не сможет отличить curl от браузера. Ответ на вопрос, почему это не работает, должен быть в $info - person Misunderstood; 20.03.2015
comment
Мне удалось воспроизвести его с помощью этой ссылки: заголовок stackoverflow.com/questions/18318052/ - person Th3lmuu90; 21.03.2015
comment
Любопытно, удалось ли вам увидеть заголовок запроса в браузере с помощью Chrome Dev Tools или FireFox Inspector, как я предложил? Я не понимаю, зачем вам нужна дополнительная информация. Все, что вам нужно было знать, должно было быть в заголовках запросов. - person Misunderstood; 21.03.2015