Заставьте cURL записывать данные по мере их получения - PullRequest
2 голосов
/ 05 октября 2009

У меня есть следующий php-код, который я нашел здесь :

function download_xml()
{
    $url = 'http://tv.sygko.net/tv.xml';

    $ch = curl_init($url);
    $timeout = 5;

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);

    $data = curl_exec($ch);

    echo("curl_exec was succesful"); //This never gets called

    curl_close($ch);
    return $data;
}

$my_file = 'tvdata.xml';
$handle = fopen($my_file, 'w');
$data = download_xml();
fwrite($handle, $data);

Я пытаюсь загрузить XML-файл по указанному URL-адресу и сохранить его на диск. Тем не менее, он останавливается примерно на 80% и никогда не достигает вызова echo после вызова curl_exec. Я не уверен, почему, но я верю, что это потому, что у него заканчивается память. Поэтому я хотел бы спросить, можно ли заставить curl записывать данные в файл каждый раз, когда он скачал, скажем, 4 КБ. Если это невозможно, кто-нибудь знает способ получить файл XML, сохраненный по URL-адресу, загруженный и сохраненный на моем диске с помощью php?

Большое спасибо, БЕН.

EDIT: Это код сейчас, он не работает. Он записывает данные в файл, но все еще только около 80% документа. Может быть, это не потому, что он превышает память, а по какой-то другой причине? Я действительно не могу поверить, что это так сложно скопировать файл с URL на диск ...

    <?

$url = 'http://tv.sygko.net/tv.xml';
$my_file = fopen('tvdata.xml', 'w');

$ch = curl_init($url);
$timeout = 300;

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FILE, $my_file);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
    curl_setopt($ch, CURLOPT_BUFFERSIZE, 4096);

curl_exec($ch) OR die("Error in curl_exec()");

echo("got to after curl exec");

fclose($my_file);
curl_close($ch);

    ?>

Ответы [ 4 ]

5 голосов
/ 26 марта 2013

Вот вам полностью рабочий пример:

public function saveFile($url, $dest) {

        if (!file_exists($dest))
                touch($dest);

        $file = fopen($dest, 'w');
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, 'progressCallback');
        curl_setopt($ch, CURLOPT_BUFFERSIZE, (1024*1024*512));
        curl_setopt($ch, CURLOPT_NOPROGRESS, FALSE);
        curl_setopt($ch, CURLOPT_FAILONERROR, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 15);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');
        curl_setopt($ch, CURLOPT_FILE, $file);

        curl_exec($ch);
        curl_close($ch);

        fclose($file);
}
?>

Секрет в том, что для CURLOPT_NOPROGRESS задано значение FALSE, а затем CURLOPT_BUFFERSIZE создаст отчет об обратном вызове для всех достигнутых байтов CURLOPT_BUFFERSIZE. Чем меньше значение, тем чаще оно будет сообщаться. Это также зависит от вашей скорости загрузки и т. Д., Поэтому не рассчитывайте, что она будет сообщать каждые X секунд, поскольку она будет сообщать о каждом полученном / переданном байте X.

3 голосов
/ 05 октября 2009

Ваш тайм-аут установлен на 5 секунд, которые могут быть слишком короткими в зависимости от размера файла документа. Попробуйте увеличить его до 10-15, чтобы убедиться, что у него достаточно времени для завершения передачи.

2 голосов
/ 05 октября 2009

Существует опция CURELOPT_FILE, которая позволяет вам указать файл обработчик , в который должен записывать curl. Я почти уверен, что он будет делать «правильно» и «писать» во время чтения, избегая проблем с памятью

$file = fopen('test.txt', 'w'); //<--------- file handler
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,'http://example.com');
curl_setopt($ch, CURLOPT_FAILONERROR,1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_FILE, $file);   //<------- this is your magic line
curl_exec($ch); 
curl_close($ch);
fclose($file);
1 голос
/ 05 октября 2009

curl_setopt CURLOPT_FILE - Файл, в который должна быть записана передача. По умолчанию используется STDOUT (окно браузера)

http://us2.php.net/manual/en/function.curl-setopt.php

...