Téléchargement d'un fichier volumineux à l'aide de curl


86

J'ai besoin de télécharger un fichier distant en utilisant curl.

Voici l'exemple de code que j'ai:

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

Mais il ne peut pas gérer de gros fichiers, car il lit d'abord en mémoire.

Est-il possible de diffuser le fichier directement sur le disque?

Réponses:


167
<?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
Défendez votre commentaire @ yes123, ça m'intéresse de savoir.
— Jürgen Paul

8
Corrigez-moi si je me trompe, mais je ne pense pas que vous ayez réellement besoin de manuellement fwriteles données depuis que vous les utilisez CURLOPT_FILE.
— Sasha Chedygov

1
Comme @SashaChedygov l'a souligné ci-dessus, vous n'avez pas besoin d'utiliser fwriteAND CURLOPT_FILE. Passer le $fpest suffisant. J'ai fait les deux et je me suis retrouvé 1à la fin du contenu du fichier.
— trombone le

@Sasha Chedygov ~ oui vous n'avez pas besoin dufwrite
— Alireza

5
Il semble que la définition de CURLOPT_FILE avant la définition de CURLOPT_RETURNTRANSFER ne fonctionne pas, probablement parce que CURLOPT_FILE dépend de la définition de CURLOPT_RETURNTRANSFER. php.net/manual/en/function.curl-setopt.php#99082
— Nabi KAZ

25

J'utilise cette fonction pratique:

En le téléchargeant avec une étape de 4094 octets, il ne remplira pas votre mémoire

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

Usage:

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

Vous pouvez ensuite vérifier si tout va bien avec:

     if (!$result)
         throw new Exception('Download error...');

1
@Severus vous attrapez une erreur http comme fopen()renvoyant false et timeout vous le mettez dans la boucle while (appelez time()et faites le calcul)
— Silviu-Marian

2
cURL a déjà une implémentation fonctionnelle de ceci (voir la réponse acceptée), pourquoi voudriez-vous implémenter quelque chose par vous-même?
— Petr Peller

2
Parce que l'interface procédurale cURL est assez mauvaise
— dynamique

pour ce que ça vaut, j'ai utilisé stream_copy_to_streamau lieu de copier manuellement le contenu, fait un code plus court. Ni ceci ni cela fonctionne avec https(sauf si vous stipulez a $context). Style procédural concerté - les fonctions de fichier ne sont pas non plus tout à fait OOP, et si vous mettez des options curl dans un tableau, cela aura l'air beaucoup plus propre de toute façon.
— ashein

Je l'ai testé avec un https, fonctionne très bien !!!, Merci pour votre aide @dynamic.
— Ozal Zarbaliyev

6

Trouvez le code ci-dessous si vous souhaitez télécharger le contenu de l'URL spécifiée et souhaitez l'enregistrer dans un fichier.

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

Si vous souhaitez télécharger un fichier à partir du serveur FTP, vous pouvez utiliser l'extension FTP php. Veuillez trouver ci-dessous le 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);
?>

4

quand curlest utilisé pour télécharger un fichier volumineux, CURLOPT_TIMEOUTc'est l'option principale que vous devez définir.

CURLOPT_RETURNTRANSFER doit être vrai au cas où vous auriez un fichier comme pdf / csv / image, etc.

Vous pouvez trouver plus de détails ici (URL correcte) Curl Doc

À partir de cette page:

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

Vous pouvez également consulter l'exemple du blog concernant le téléchargement de fichiers avec curl comprenant les bases de curl
— prashant pandey

2

Vous pouvez utiliser cette fonction, qui crée un fichier temporaire dans le système de fichiers et renvoie le chemin du fichier téléchargé si tout a fonctionné correctement:

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;
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.