#php #curl #libcurl
#php #curl #libcurl
Вопрос:
Я хочу правильно понять функцию CURLOPT_READFUNCTION.
Я смотрю на Rackspace coudfiles php-код (REST API).
В нем есть следующая строка.
curl_setopt($ch, CURLOPT_READFUNCTION, array(amp;$this, '_read_cb'));
Рассматриваем определение этой функции:
private function _read_cb($ch, $fd, $length)
{
$data = fread($fd, $length);
$len = strlen($data);
if (isset($this->_user_write_progress_callback_func)) {
call_user_func($this->_user_write_progress_callback_func, $len);
}
return $data;
}
Можете ли вы помочь мне понять, какие значения передаются в $ fd и $ length?
Я хочу конкретно указать значение $length, чтобы отправлять файл частями.
Заранее спасибо.
Комментарии:
1. С помощью curl вы читаете URL-адреса, а не отправляете фрагменты. Что вы пытаетесь?
2. Интересно. Руководство здесь неверно, в нем говорится, что обратный вызов принимает только два параметра.
Ответ №1:
Я знаю, что это немного некро, но другие люди, возможно, захотят узнать, как это работает.
Вот как будет выглядеть типичный блок размещения файла curl:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $ret['Location']);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_PUT, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
curl_setopt($ch, CURLOPT_READFUNCTION, 'curlPutThrottle');
curl_setopt($ch, CURLOPT_INFILE, $fh);
curl_setopt($ch, CURLOPT_INFILESIZE, $size);
$ret = curl_exec($ch);
и функция чтения выглядела бы примерно так (она регулирует скорость, заданную пользователем $ goal, и выдает обратную связь с отображением CLI)
function curlPutThrottle($ch, $fh, $length = false)
{
global $size;
global $current;
global $throttle;
global $start;
/** Set your max upload speed - here 30mB / minute **/
$goal = (300*1024*1024)/(60*10);
if (!$length)
{
$length = 1024 * 1024;
}
if (!is_resource($fh))
{
return 0;
}
$current = $length;
if ($current > $throttle) /** Every meg uploaded we update the display and throttle a bit to reach target speed **/
{
$pct = round($current/$size*100);
$disp = "Uploading (".$pct."%) - ".number_format($current, 0).'/'.number_format($size, 0);
echo "r ".$disp.str_repeat(" ", strlen($disp));
$throttle = 1024*1024;
$elapsed = time() - $start;
$expectedUpload = $goal * $elapsed;
if ($current > $expectedUpload)
{
$sleep = ($current - $expectedUpload) / $goal;
$sleep = round($sleep);
for ($i = 1; $i <= $sleep; $i )
{
echo "r Throttling for ".($sleep - $i 1)." Seconds - ".$disp;
sleep(1);
}
echo "r ".$disp.str_repeat(" ", strlen($disp));
}
}
if ($current > $size)
{
echo "n";
}
return fread($fh, $length);
}
Где:
- $ch — это ресурс cURL, который вызывает функцию ReadFunction
- $ fh — это дескриптор файла из CURLOPT_INFILE
- $length — это объем данных, который он ожидает получить обратно.
Она возвращает данные из файла длиной $length или «if EOF.
Ответ №2:
Руководство, похоже, здесь неверно:
CURLOPT_READFUNCTION
Имя функции обратного вызова, где функция обратного вызова принимает два параметра. Первый — это ресурс cURL, а второй — строка с данными для чтения. Данные должны быть прочитаны с помощью этой функции обратного вызова. Возвращает количество прочитанных байтов. Верните 0 для обозначения EOF.
На самом деле она принимает три параметра (см. Исходный код):
- Первый — это дескриптор curl.
- Второй — это поток PHP, который задается с помощью опции
CURLOPT_INFILE
. - Третий — это объем данных, который должен быть считан из потока PHP и передан в библиотеку curl, чтобы она могла отправить его на HTTP-сервер.
РЕДАКТИРОВАТЬ: Исправлено в этом коммите.
Комментарии:
1. Я пытаюсь загрузить большой файл (около 2 ГБ) с помощью этого API, но это не удается. Вероятно, из-за ограничения памяти на общем сервере. Есть ли какой-нибудь способ читать небольшими фрагментами и отправлять файл? (например, прочитать 20 мб данных, отправить, выполнить цикл до EOF. Я знаю, что это можно сделать с помощью fopen / fread, но мне интересно, возможно ли это с помощью этой опции curl)
2. @KingCrunch — Я пытаюсь отправить / загрузить файл по некоторому URL