CURL - ограничения размера файла

GrayMaster

Новичок
CURL - ограничения размера файла

Такая проблема...
Юзаю CURL для скачивания страничек, чтоб скрипт не вис, сделал ограничения по времени:
PHP:
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLE_OPERATION_TIMEOUTED, 30);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
Но скрипт всё же виснет :)
А виснет из-за того, что иногда пытается качать сильно большие файлы...
Как сделать ограничения, чтоб например больше 5 мб не качал ?
 

SiMM

Новичок
В общем случае, если не ошибаюсь - никак, в частном - CURLOPT_RANGE
 

nikit87

Новичок
GrayMaster
я тут подумал над этим и придумал тока один вариант. правда для извращенцев)))))) очень сильных извращенцев))
Грузишь с помощью курла главную страницу хоста, потом curl_getinfo() - узнаешь среднюю скорость закачки. Следующий шаг - делишь свой максимальный размер файла на эту скорость и получаешь время его закачки. Ставишь CURLOPT_LOW_SPEED_LIMIT очень большим. а в CURLOPT_LOW_SPEED_TIME ставишь время которое получил до этого))))
Но это так по-моему)) если делать больше нечего))
 

DiMA

php.spb.ru
Команда форума
именно CURLOPT_RANGE и нужно использовать, работает

но это не прокатит на веб-сервере, который не поддерживает докачку и курл будет чесно скачивать гигабайтный файл

еще 3 серьезных недостатка курла:
1. нет обратной связи с php до завершения (например, для прогресс бара)
2. нет реакции на полученные заголовки, чтобы решить: скачивать или не скачивать (например, нельзя качать text/html более 100 Кб, text/plain более 10 Кб, а лимитов на */* нет)
3. если хост нельзя резолвить (DNS висит), то курл будет 30 секунд тормозить (fsockopen позволяет поставить таймаут в 5 секунд на такой случай)

И просто мелкий баг: если просить curl НЕ обрабатывать Location и не скачивать документ по новому адресу, то почему он это все равно делает.
 

GrayMaster

Новичок
2nikit87:
Почти формулу вывел :)

2DiMA:
С сокетами у вообще были нереальные глюки, когда много потоков было... Когда канал забивался, сокеты неработали. Пришлось переходить на курл.
 

gray07

Новичок
Вообще можно использовать CURLOPT_WRITEFUNCTION и прервать скачивание, если файл слишком большой.

з.ы. что-то плохо php поддерживает curl
 

whirlwind

TDD infected, paranoid
2. нет реакции на полученные заголовки, чтобы решить: скачивать или не скачивать (например, нельзя качать text/html более 100 Кб, text/plain более 10 Кб, а лимитов на */* нет)
а кто мешает предварительно HEAD запросить?
 

SiMM

Новичок
> а кто мешает предварительно HEAD запросить?
В общем случае для динамики это абсолютно бессмысленно.
 

whirlwind

TDD infected, paranoid
GrayMaster мож у мну дока устарела, но CURLOPT_WRITEFUNCTION я не нашел.
Попробуй и правда CURLOPT_RANGE с указанием 0-maxsize. После скачки проверишь по заголовкам - либо будет отличаться код (200/206) или если это не сработает, тогда по Content-Length сравнивай реальную и скачанную, или Content-Range - в нем указан полный размер файла/страницы.
 

whirlwind

TDD infected, paranoid
ну тогда HEAD предварительный, как я уже говорил ранее. Там сразу узнаешь и размер, и поддерживает ли докачку...
 

Double Flash

Новичок
Похожая ситуация. Отличия следующие:
а) у меня используется curl_multi...
б) соединение идет через SOCKS5 прокси

Результат: если с проксей все ок, худо-будно нормально работает. Если сокс лежит, функция curl_multi_exec($curl_master, $running) зависает на второй итерации цикла. И висит продолжительное время (в зависимости от количества потоков: 3-4 - 50-60 секунд, 4-7 - 80-120), после чего цикл продолжается, все curl-хендлеры отрабатываются, но курл заявляет об ошибке таймаута (он поставлен 20 секунд).

Кто подскажет, как заставить курл прерывать работу по таймауту? Я так понимаю это глюк его, кто сталкивался?

Вот опции:
CURLOPT_URL => $dest_host.'/test.php',
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HEADER => false,
CURLOPT_LOW_SPEED_LIMIT => 2048,
CURLOPT_LOW_SPEED_TIME => 10,
CURLOPT_TIMEOUT => 20,
CURLOPT_CONNECTTIMEOUT => 20,
CURLOPT_USERAGENT => 'agent',
CURLOPT_POST => 1,
CURLOPT_PROXYTYPE => CURLPROXY_SOCKS5,
CURLOPT_PROXY => $proxy_list[$i],
CURLOPT_PROXYUSERPWD => "user:password",
CURLOPT_POSTFIELDS => 'command=Test'


если вдруг кому интересно - код:
$started = time();
// checking proxies:
$proxy_list = explode("\n", str_replace("\r", '', $proxylist));
$proxy_count = count($proxy_list);
$curl_common_opt = array(CURLOPT_URL => $dest_host.'/test.php',
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HEADER => false,
CURLOPT_LOW_SPEED_LIMIT => 2048,
CURLOPT_LOW_SPEED_TIME => 10,
CURLOPT_TIMEOUT => 90,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_USERAGENT => 'Transferer sender',
CURLOPT_POST => 1,
CURLOPT_PROXYTYPE => CURLPROXY_SOCKS5);
$curl_master = curl_multi_init();
$curl_handlers = array();

for ($i = 0; $i < $proxy_count; $i++)
// preparing multi curl task:
{
$curl_handlers[$i] = curl_init();
curl_setopt_array($curl_handlers[$i], $curl_common_opt + array(CURLOPT_PROXY => $proxy_list[$i], CURLOPT_PROXYUSERPWD => "user:password", CURLOPT_POSTFIELDS => 'command=Test'));
curl_multi_add_handle($curl_master, $curl_handlers[$i]);
}

$going = $proxy_count;
do
// implementing multi curl task:
{
if (@file_exists(DIR_CONTROLERS."/transf_send_stop.cntrl")) die('Manual stop');

curl_multi_exec($curl_master, $running);
if ($running < $going)
{
echo ($going-$running)." proxy test completed. now testing ".$running." proxies<br>\n";
$going = $running;
}
sleep(2);
echo "ch prx ($running); time: ".time()."<br>\n";
}
while ($running > 0);

for($i = 0; $i < $proxy_count; $i++)
// capturing multi task results:
{
$result = curl_multi_getcontent($curl_handlers[$i]);
if (curl_errno($curl_handlers[$i]) || $result != 'Test OK')
// if page was not got (proxy down):
{
if ($show_report) echo "Proxy ".$proxy_list[$i]." is down<br>\n";
echo curl_error($curl_handlers[$i])."<br>\n";
echo $result."<br>\n---------------------<br>\n";
unset($proxy_list[$i]);
}
curl_multi_remove_handle($curl_master, $curl_handlers[$i]);
curl_close($curl_handlers[$i]);
}
$proxy_list = array_merge($proxy_list, array());
echo "test took ".(time()-$started)." sec.<br>\n";
if (!count($proxy_list)) die("All proxies are down<br>\n");

die('test completed');

За стиль извиняюсь - не нашел, как на этом форуме код форматировать.
 

Double Flash

Новичок
Автор оригинала: whirlwind
Оскара за мегадиггерство! :)
Извините?

-~{}~ 31.07.08 14:02:

whirlwind
Аааа... Вы это про 30.09.05 08:41, 31.07.08 12:52? :)

Поусердней юзайте поиск - и пальма первенства Ваша! :р
 

gray07

Новичок
Когда-то юзал curl_multi, но потом переписал на соккеты. Проблемы правда другие были :)
 

Double Flash

Новичок
Автор оригинала: gray07
Когда-то юзал curl_multi, но потом переписал на соккеты. Проблемы правда другие были :)
Полноценно победить проблему не удалось, к сожалению. Сокеты штука хорошая, но уж больно у КУРЛа инструментарий богат, сам столько не наваяешь.

Но это лирика. А вот мыслишки, как победить трабл есть.

Вариант айн: запускать php скрипты с сингловыми курл задания в параллельных процессах (нафоркать их, ну или более примитивно, через командную строку в фоновом режиме запускать). Тут есть недостаток в чрезмерном расходе памяти.
Вариант цвай: не морочить себе голову и запускать параллельно скрипту не пыхпышный а обычный никсовый курл (а вот как запускать - тут уж вариантов много).

Ну а в материнском скрипте просто ждать результаты.
 
Сверху