Модераторы: Aliance, skyboy, MoLeX, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> CURL and POST, отправка файла методом POST 
:(
    Опции темы
slva2000
Дата 26.11.2009, 07:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 50
Регистрация: 29.10.2005

Репутация: нет
Всего: нет



Так и не нашёл подтверждения своих мыслей. Задача проста: отправить форму методом пост, посредствам библиотеки CURL. Сложность заключается в отправке вместе с формой ФАЙЛА.

Использую следующий код:

Код

function post($url,$data) { 

$process = curl_init($url); 

curl_setopt($process, CURLOPT_HEADER, 0); 
curl_setopt($process, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0)"); 

curl_setopt($process, CURLOPT_POSTFIELDS, $data); 
curl_setopt($process, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($process, CURLOPT_FOLLOWLOCATION, 1); 
curl_setopt($process, CURLOPT_POST, 1); 
$return = curl_exec($process); 
curl_close($process); 
return $return; 
}


$post_data = "name=USER&NAME_input_FORM_file=filename=\"my_file.jpg\" Content-Type: image/jpeg";

echo post("site.ru", $post_data);


Сайт удалённый (посмотреть что получает $_POST[file] не могу)

В результате форма принимает name (USER) а файл не подгружается. Выполняю из под Apatch (win32), файл лежит в корне скрипта (пробовал и с:\\my_file.jpg и с://my_file.jpg).

Замучался, поясните где ошибка..
PM MAIL   Вверх
slva2000
  Дата 26.11.2009, 13:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 50
Регистрация: 29.10.2005

Репутация: нет
Всего: нет



Уф, ну и не разбериха с этим курлом... Нашёл две детали (только с отладочными скриптами):

1. CURLOPT_POST должна идти обязательно перед CURLOPT_POSTFIELDS (иначе не принимает файл)
2. Заголовки я формировал для своей функции классические:

Код

$this->headers[] = 'Accept: image/gif, image/x-bitmap, image/jpeg, image/pjpeg'; 
$this->headers[] = 'Connection: Keep-Alive'; 
$this->headers[] = 'Content-type: application/x-www-form-urlencoded;charset=UTF-8'; 
$this->user_agent = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0)'; 


С ними отправить файл не удавалось. Что ж, решил скопировать заголовки со снифера (реальный пост на сайте):

Код

$head[] = "Content-Type: image/gif";

$head[] = "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10";
$head[] = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
$head[] = "Accept-Language: ru,en-us;q=0.7,en;q=0.3";
$head[] = "Accept-Encoding: gzip,deflate";
$head[] = "Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7";
$head[] = "Keep-Alive: 300";
$head[] = "Connection: keep-alive";
$head[] = "Referer: http:/xxx.ru/";
$head[] = "Content-Type: multipart/form-data";


Тоже не принимал такие. Удалил CURLOPT_HTTPHEADER с функции, всё заработало. Файл был принят сервером.
В голове не осталось ничего полезного  smile

Добавлено через 8 минут и 5 секунд
Забыл добавить:

CURLOPT_POSTFIELDS должен быть массивом:

array("name_input" => "value");
PM MAIL   Вверх
Pitlord
Дата 26.11.2009, 17:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 246
Регистрация: 31.10.2009

Репутация: 1
Всего: 7



Стоит читать мануал (http://php.net/manual/en/function.curl-setopt.php):

Код

<?php
$ch = curl_init();

$data = array('name' => 'Foo', 'file' => '@/home/user/test.png');

curl_setopt($ch, CURLOPT_URL, 'http://localhost/upload.php');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

curl_exec($ch);
?>

(обрати внимание на символ "@")

Цитата(slva2000 @  26.11.2009,  13:59 Найти цитируемый пост)
Заголовки я формировал для своей функции классические

А кто просит тебя формировать Content-type? При передачи файла Content-type другой: multipart/form-data (+ boundary).

Добавлено через 2 минуты и 46 секунд
Тут статья на тему как оформляются заголовки при передаче файла: http://phpclub.ru/detail/article/http_request#part_3_2

Это сообщение отредактировал(а) Pitlord - 26.11.2009, 17:52
PM MAIL   Вверх
slva2000
Дата 27.11.2009, 09:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 50
Регистрация: 29.10.2005

Репутация: нет
Всего: нет



Pitlord
обясни мне пожалуйста следующие вещи:

Три примера, работает только первый. Второй имеет строку (вместо массива) для передачи POST значений, а третий, порядок POSTFIELDS.

upload.php:

Код
<?
print_r($_POST);
echo "<br><br>";
print_r($_FILES);
?>



(не забудь положить 0.gif в ./home/localhost/)

Варинат 1. (единственный рабочий из предложеных)

index.php:

Код
<?php
$ch = curl_init();
$data = array('name' => 'Foo', 'file' => '@'.$_SERVER['DOCUMENT_ROOT'].'/0.gif');

curl_setopt($ch, CURLOPT_URL, 'http://localhost/upload.php');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_exec($ch);
?>



Варинат 2. (Стройка вместо массива. НЕ рабочий)

index.php:

Код
<?php
$ch = curl_init();
$data = "name=Foo&file=@".$_SERVER['DOCUMENT_ROOT']."/0.gif";

curl_setopt($ch, CURLOPT_URL, 'http://localhost/upload.php');
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_POST, 1);
curl_exec($ch);
?>



Варинат 3. (CURLOPT_POST после CURLOPT_POSTFIELDS. НЕ рабочий)

index.php:

Код
<?php
$ch = curl_init();
$data = array('name' => 'Foo', 'file' => '@'.$_SERVER['DOCUMENT_ROOT'].'/0.gif');

curl_setopt($ch, CURLOPT_URL, 'http://localhost/upload.php');
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_POST, 1);
curl_exec($ch);
?>


Добавлено через 3 минуты и 45 секунд
ЗЫ: статья по заголовкам хорошая. Спасибо.

Это сообщение отредактировал(а) slva2000 - 27.11.2009, 09:45
PM MAIL   Вверх
Pitlord
Дата 27.11.2009, 19:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 246
Регистрация: 31.10.2009

Репутация: 1
Всего: 7



Цитата(slva2000 @  27.11.2009,  09:43 Найти цитируемый пост)
Варинат 2. (Стройка вместо массива. НЕ рабочий)

Цитата(slva2000 @  27.11.2009,  09:43 Найти цитируемый пост)
$data = "name=Foo&file=@".$_SERVER['DOCUMENT_ROOT']."/0.gif";

Ты пытаешься формировать POST-запрос для Content-type "application/x-www-form-urlencoded", а для "multipart/form-data" он формируется абсолютно по-другому, читай статью, что я привёл.

К тому же символ "@" — просто специальное обозначение cURL'а, он с протоколом HTTP не связан.

Цитата(slva2000 @  27.11.2009,  09:43 Найти цитируемый пост)
Варинат 3. (CURLOPT_POST после CURLOPT_POSTFIELDS. НЕ рабочий)

Не знаю, лень проверять. Вообще флаг CURLOPT_POST необязательно ставить, он выставится автоматически при непустом CURLOPT_POSTFIELDS или CURLOPT_FILE
PM MAIL   Вверх
slva2000
Дата 28.11.2009, 07:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 50
Регистрация: 29.10.2005

Репутация: нет
Всего: нет



Pitlord спасибо. На счёт "варинат 2" понял. Я так и подозревал, но думал, может контент-тип можно указать в строке?

Код

$data = "name=Foo&file=".$_SERVER['DOCUMENT_ROOT']."/0.gif Content-type: image/gif";


Но и так не сработало... 

Цитата

Не знаю, лень проверять


а вот очень зря. В мануале написано: порядок curl_setopt не имеет значения. Но в примере, который я привёл и проверил, оказывается имеет. Замечу, при посылке ПОСТ запросов с параметрами в строке (без передачи файла, и с Цонтент-тыпе Content-type "application/x-www-form-urlencoded") порядок действительно не имеет значения. А если параметры массив - и ....multipart/form-data - то, строго так как я говорил.

Не поленись, проверь пожалуйста. Это парадокс!
PM MAIL   Вверх
Pitlord
Дата 28.11.2009, 22:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 246
Регистрация: 31.10.2009

Репутация: 1
Всего: 7



Цитата(slva2000 @  28.11.2009,  07:26 Найти цитируемый пост)
а вот очень зря. В мануале написано: порядок curl_setopt не имеет значения. Но в примере, который я привёл и проверил, оказывается имеет. Замечу, при посылке ПОСТ запросов с параметрами в строке (без передачи файла, и с Цонтент-тыпе Content-type "application/x-www-form-urlencoded") порядок действительно не имеет значения. А если параметры массив - и ....multipart/form-data - то, строго так как я говорил.

Ну, в принципе, согласно документации, если ты передаёшь массив параметру CURLOPT_POSTFIELDS, то Content-type станет "multipart/form-data":
Цитата

If value  is an array, the Content-Type header will be set to multipart/form-data. 

А CURLOPT_POST устанавливает Content-type "application/x-www-form-urlencoded":
Цитата

This POST is the normal application/x-www-form-urlencoded kind, most commonly used by HTML forms. 

, поэтому при загрузке файлов CURLOPT_POST вообще не надо устанавливать.

Я проверил на версии PHP 5.2.5 — действительно во втором случае "application/x-www-form-urlencoded" и данные POST-запроса вообще обнуляются (Content-length: 0).

Это сообщение отредактировал(а) Pitlord - 28.11.2009, 22:27
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Сеть | Следующая тема »


 




[ Время генерации скрипта: 0.0522 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.