Herunterladen einer großen Datei mit Curl

86

Ich muss die Remote-Datei mit Curl herunterladen.

Hier ist der Beispielcode, den ich habe:

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

Es kann jedoch keine großen Dateien verarbeiten, da es zuerst in den Speicher liest.

Ist es möglich, die Datei direkt auf die Festplatte zu streamen?

Kusanagi
quelle

Antworten:

166
<?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);
?>
Das Gehirn
quelle
5
Verteidige deinen Kommentar @ yes123, ich bin interessiert zu wissen.
Jürgen Paul
8
Korrigieren Sie mich, wenn ich falsch liege, aber ich glaube nicht, dass Sie fwritedie Daten manuell verwenden müssen, da Sie sie verwenden CURLOPT_FILE.
Sasha Chedygov
1
Wie @SashaChedygov oben ausgeführt hat, müssen Sie fwriteAND nicht verwenden CURLOPT_FILE. Das zu bestehen $fpist genug. Ich habe beides getan und bin 1am Ende des Inhalts in der Datei gelandet.
Büroklammer
@ Sasha Chedygov ~ ja, du brauchst das nichtfwrite
Alireza
5
Es scheint, dass das Festlegen von CURLOPT_FILE vor dem Festlegen von CURLOPT_RETURNTRANSFER nicht funktioniert, vermutlich weil CURLOPT_FILE vom Festlegen von CURLOPT_RETURNTRANSFER abhängt. php.net/manual/en/function.curl-setopt.php#99082
Nabi KAZ
25

Ich benutze diese praktische Funktion:

Wenn Sie es mit einem 4094-Byte-Schritt herunterladen, wird Ihr Speicher nicht voll

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

Verwendung:

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

Sie können dann überprüfen, ob alles in Ordnung ist mit:

     if (!$result)
         throw new Exception('Download error...');
dynamisch
quelle
1
@Severus Sie fangen http Fehler als fopen()Rückgabe falsch und Timeout Sie setzen es in die while-Schleife (rufen Sie an time()und rechnen Sie )
Silviu-Marian
2
cURL hat bereits eine funktionierende Implementierung (siehe die akzeptierte Antwort). Warum sollten Sie etwas selbst implementieren wollen?
Petr Peller
2
Weil die prozedurale Schnittstelle von cURL ziemlich schlecht ist
dynamisch
Für das, was es wert ist, habe ich verwendet, stream_copy_to_streamanstatt Inhalte manuell zu kopieren, macht einen kürzeren Code. Weder dies noch das funktionieren mit https(es sei denn, Sie legen a fest $context). Konzertieren Sie den prozeduralen Stil - Dateifunktionen sind auch nicht ganz OOP, und wenn Sie Curl-Optionen in ein Array einfügen, sieht es sowieso viel sauberer aus.
Ashein
Ich habe es mit einem https getestet, funktioniert super !!!, Danke für deine Hilfe @dynamic.
Ozal Zarbaliyev
6

Suchen Sie den folgenden Code, wenn Sie den Inhalt der angegebenen URL herunterladen und in einer Datei speichern möchten.

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

Wenn Sie Dateien vom FTP-Server herunterladen möchten, können Sie die PHP-FTP-Erweiterung verwenden. Nachfolgend finden Sie den Code:

<?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
quelle
4

Wenn curlzum Herunterladen einer großen Datei verwendet wird, CURLOPT_TIMEOUTist dies die Hauptoption, für die Sie festlegen müssen.

CURLOPT_RETURNTRANSFER muss wahr sein, wenn Sie Dateien wie pdf / csv / image usw. erhalten.

Weitere Details finden Sie hier (korrekte URL) Curl Doc

Von dieser Seite:

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 pandey
quelle
Sie können auch das Blog-Beispiel zum Herunterladen von Dateien mit Curl- Verständnis für Curl-Grundlagen
durchgehen
2

Sie können diese Funktion verwenden, die eine Tempfile im Dateisystem erstellt und den Pfad zur heruntergeladenen Datei zurückgibt, wenn alles einwandfrei funktioniert hat:

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
quelle