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?

kusanagi
la source

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);
?>
Le cerveau
la source
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...');
dynamique
la source
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);
?>
Sanjeev Chauhan
la source
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
prashant pandey
la source
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;
}
Matthias Kleine
la source