Скачивание большого файла с помощью curl

87

Мне нужно скачать удаленный файл с помощью curl.

Вот пример кода, который у меня есть:

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

$st = curl_exec($ch);
$fd = fopen($tmp_name, 'w');
fwrite($fd, $st);
fclose($fd);

curl_close($ch);

Но он не может обрабатывать большие файлы, потому что сначала читает в память.

Можно ли передать файл прямо на диск?

кусанаги
источник

Ответы:

168
<?php
set_time_limit(0);
//This is the file where we save the    information
$fp = fopen (dirname(__FILE__) . '/localfile.tmp', 'w+');
//Here is the file we are downloading, replace spaces with %20
$ch = curl_init(str_replace(" ","%20",$url));
curl_setopt($ch, CURLOPT_TIMEOUT, 50);
// write curl response to file
curl_setopt($ch, CURLOPT_FILE, $fp); 
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
// get curl response
curl_exec($ch); 
curl_close($ch);
fclose($fp);
?>
Мозг
источник
5
Защитите свой комментарий @ yes123, мне интересно узнать.
Юрген Пол
8
Поправьте меня, если я ошибаюсь, но я не думаю, что вам действительно нужно вручную fwriteданные, поскольку вы используете CURLOPT_FILE.
Саша Чедыгов
1
Как отметил выше @SashaChedygov, вам не нужно использовать fwriteAND CURLOPT_FILE. Проходя мимо $fpдостаточно. Я сделал и то, и другое, и в итоге остался 1в конце содержимого файла.
скрепка
@Sasha Chedygov ~ да, тебе не нужнаfwrite
Алиреза
5
Похоже, что установка CURLOPT_FILE перед установкой CURLOPT_RETURNTRANSFER не работает, предположительно потому, что CURLOPT_FILE зависит от установленного CURLOPT_RETURNTRANSFER. php.net/manual/en/function.curl-setopt.php#99082
Nabi KAZ
25

Я использую эту удобную функцию:

Скачав его с шагом 4094 байта, он не заполнит вашу память

function download($file_source, $file_target) {
    $rh = fopen($file_source, 'rb');
    $wh = fopen($file_target, 'w+b');
    if (!$rh || !$wh) {
        return false;
    }

    while (!feof($rh)) {
        if (fwrite($wh, fread($rh, 4096)) === FALSE) {
            return false;
        }
        echo ' ';
        flush();
    }

    fclose($rh);
    fclose($wh);

    return true;
}

Применение:

     $result = download('http://url','path/local/file');

Затем вы можете проверить, все ли в порядке:

     if (!$result)
         throw new Exception('Download error...');
динамичный
источник
1
@Severus, вы ловите HTTP-ошибку, fopen()возвращая false и тайм-аут, вы помещаете ее в цикл while (вызовите time()и сделайте математику)
Сильвиу-Мариан
2
cURL уже имеет рабочую реализацию этого (см. принятый ответ), зачем вам реализовывать что-то самостоятельно?
Петр Пеллер
2
Потому что процедурный интерфейс cURL довольно плохой
динамический
что бы это ни стоило, я использовал stream_copy_to_streamвместо того, чтобы вручную копировать содержимое, делает более короткий код. Ни то, ни другое не работает https(если вы не указали а $context). Что касается процедурного стиля - файловые функции тоже не совсем ООП, и если вы поместите параметры curl в массив, он все равно будет выглядеть намного чище.
ashein
Я тестировал его с https, отлично работает !!!, Спасибо за помощь @dynamic.
Озал Зарбалиев
6

Найдите код ниже, если вы хотите загрузить содержимое указанного URL-адреса, а также сохранить его в файл.

<?php
$ch = curl_init();
/**
* Set the URL of the page or file to download.
*/
curl_setopt($ch, CURLOPT_URL,'http://news.google.com/news?hl=en&topic=t&output=rss');

$fp = fopen('rss.xml', 'w+');
/**
* Ask cURL to write the contents to a file
*/
curl_setopt($ch, CURLOPT_FILE, $fp);

curl_exec ($ch);

curl_close ($ch);
fclose($fp);
?>

Если вы хотите загрузить файл с FTP-сервера, вы можете использовать расширение php FTP. Пожалуйста, найдите код ниже:

<?php
$SERVER_ADDRESS="";
$SERVER_USERNAME="";
$SERVER_PASSWORD="";
$conn_id = ftp_connect($SERVER_ADDRESS);

// login with username and password
$login_result = ftp_login($conn_id, $SERVER_USERNAME, $SERVER_PASSWORD);

$server_file="test.pdf" //FTP server file path 
$local_file = "new.pdf"; //Local server file path 

##----- DOWNLOAD $SERVER_FILE AND SAVE TO $LOCAL_FILE--------##
if (ftp_get($conn_id, $local_file, $server_file, FTP_BINARY)) {
    echo "Successfully written to $local_file\n";
} else {
    echo "There was a problem\n";
}

ftp_close($conn_id);
?>
Санджив Чаухан
источник
4

когда curlиспользуется для загрузки большого файла, то CURLOPT_TIMEOUTэто основной параметр, который вам нужно настроить.

CURLOPT_RETURNTRANSFER должно быть правдой, если вы получаете файл типа pdf / csv / image и т. д.

Вы можете найти более подробную информацию здесь (правильный URL) Curl Doc

С этой страницы:

curl_setopt($request, CURLOPT_TIMEOUT, 300); //set timeout to 5 mins

curl_setopt($request, CURLOPT_RETURNTRANSFER, true); // true to get the output as string otherwise false
прашант пандей
источник
Вы также можете просмотреть в блоге пример загрузки файла с помощью curl, понимая основы завивки
prashant pandey
2

Вы можете использовать эту функцию, которая создает временный файл в файловой системе и возвращает путь к загруженному файлу, если все работает нормально:

function getFileContents($url)
{
    // Workaround: Save temp file
    $img = tempnam(sys_get_temp_dir(), 'pdf-');
    $img .= '.' . pathinfo($url, PATHINFO_EXTENSION);

    $fp = fopen($img, 'w+');

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_FILE, $fp);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

    $result = curl_exec($ch);
    curl_close($ch);

    fclose($fp);

    return $result ? $img : false;
}
Маттиас Кляйне
источник