Mendownload file besar menggunakan curl

87

Saya perlu mengunduh file jarak jauh menggunakan curl.

Berikut kode contoh yang saya miliki:

$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);

Tetapi tidak dapat menangani file besar, karena membaca ke memori terlebih dahulu.

Apakah mungkin untuk mengalirkan file langsung ke disk?

kusanagi
sumber

Jawaban:

169
<?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);
?>
Otak
sumber
5
Pertahankan komentar Anda @ yes123, saya tertarik untuk mengetahuinya.
Jürgen Paul
8
Koreksi saya jika saya salah, tetapi menurut saya Anda tidak benar-benar perlu fwritedata secara manual karena Anda menggunakan CURLOPT_FILE.
Sasha Chedygov
1
Seperti yang telah ditunjukkan @SashaChedygov di atas, Anda tidak perlu menggunakan fwriteAND CURLOPT_FILE. Melewati $fpsudah cukup. Saya melakukan keduanya dan berakhir dengan 1konten di akhir file.
penjepit kertas
@Sasha Chedygov ~ ya Anda tidak perlufwrite
Alireza
5
Tampaknya menyetel CURLOPT_FILE sebelum menyetel CURLOPT_RETURNTRANSFER tidak berfungsi, mungkin karena CURLOPT_FILE bergantung pada CURLOPT_RETURNTRANSFER yang disetel. php.net/manual/en/function.curl-setopt.php#99082
Nabi KAZ
25

Saya menggunakan fungsi praktis ini:

Dengan mendownloadnya dengan langkah 4094 byte tidak akan memenuhi memori Anda

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;
}

Pemakaian:

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

Anda kemudian dapat memeriksa apakah semuanya baik-baik saja dengan:

     if (!$result)
         throw new Exception('Download error...');
dinamis
sumber
1
@Severus Anda menangkap kesalahan http sebagai fopen()mengembalikan salah dan batas waktu Anda meletakkannya di loop sementara (panggil time()dan lakukan matematika)
Silviu-Marian
2
cURL sudah memiliki implementasi yang berfungsi untuk ini (lihat jawaban yang diterima), mengapa Anda ingin menerapkan sesuatu sendiri?
Petr Peller
2
Karena antarmuka prosedural cURL sangat buruk
dinamis
untuk apa nilainya, saya telah menggunakan stream_copy_to_streamalih-alih menyalin konten secara manual, membuat kode yang lebih pendek. Baik ini maupun itu tidak berfungsi dengan https(kecuali Anda menetapkan a $context). Gaya prosedural konser - fungsi file juga tidak cukup OOP, dan jika Anda meletakkan opsi curl dalam array, itu akan terlihat jauh lebih bersih.
ashein
Saya mengujinya dengan https, berfungsi dengan baik !!!, Terima kasih atas bantuan Anda @dynamic.
Ozal Zarbaliyev
6

Temukan kode di bawah ini jika Anda ingin mendownload isi dari URL yang ditentukan juga ingin menyimpannya ke sebuah file.

<?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);
?>

Jika Anda ingin mendownload file dari server FTP Anda dapat menggunakan ekstensi php FTP. Silakan temukan kode di bawah ini:

<?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);
?>
Sanjeev Chauhan
sumber
4

ketika curldigunakan untuk mengunduh file besar maka itu CURLOPT_TIMEOUTadalah opsi utama yang harus Anda atur.

CURLOPT_RETURNTRANSFER harus benar jika Anda mendapatkan file seperti pdf / csv / image dll.

Anda dapat menemukan detail lebih lanjut di sini (url benar) Curl Doc

Dari halaman itu:

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
Prashant
sumber
Anda juga dapat melihat contoh blog mengenai pengunduhan file dengan pemahaman curl dasar
Prashant
2

Anda dapat menggunakan fungsi ini, yang membuat file temporer di sistem file dan mengembalikan jalur ke file yang diunduh jika semuanya bekerja dengan baik:

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;
}
Matthias Kleine
sumber