Sauvegarder une image depuis une url en utilisant php
On a tous un jour eu la bonne idée de chopper une image sur le site d'un autre type, pour un design ou pour un article ou pour illustrer n'importe quoi d'autre (par exemple) , bon osef :) Et du coup ce même jour (un peu plus tard), on s'est dit qu'on pourrait surement aussi aller chercher ce fichier image depuis une URL, pour par exemple, automatiser la chose ou que sais je encore...
C'est à ce moment précis qu'on se demande quelle sont les possibilités et quelle est celle qu'on va choisir surtout. On a toujours différents choix, selon les paramètres et disponibilités de l’environnement sous lequel on est en train de travailler.
Quelques exemples
En partant du principe ou on ira toujours chercher un fichier image qui se trouve au bout de l'URL qui sera contenue dans la variable $url suivante :
$url = 'http://www.mondomaine.com/son_image.jpg';
En imaginant aussi qu'on a les droits d'écriture dans le dossier de destination choisi, ces erreurs reviennent aussi souvent qu'elles sont bêtes donc bon, je le précise quand même :)
$fichier = $_SERVER['DOCUMENT_ROOT'].'/test/image_test.jpg';
Donc on a une solution qui semble être courte, merveilleuse et élégante qui consiste à utiliser la fonction php copy . Pour fonctionner cette fonction requiert l'option allow_url_fopen qui active certaines fonctions d'accès au fichiers. Pensez aussi à votre header (si il veut manger du image/jpeg, il aura du mal avec le png, surtout avec la transparence).
copy($url, $fichier);
On peut aussi faire le boulot d'une autre manière, en créant une fonction qui pourrait gérer ça d'une façon ...plus binaire on va dire
function choppe_image($_url,$_fichier){ $in= fopen($_url, "rb"); $out= fopen($_fichier, "wb"); // tant qu'il y a des 1 et des 0, on boucle while ($brut = fread($in,8192)){ // on les ecrits dans le fichier de sortie fwrite($out, $brut, 8192); } fclose($in); // on referme l'ouverture sur le fichier source fclose($out);// on referme le fichier qu'on vient de creer } choppe_image($url,$fichier);
Si il y a un problème, modifiez le rapport d'erreur provisoirement error_reporting(E_ALL|E_STRICT) et vérifiez le joli message d'erreur que php vous envoie ;)
Si vous avez l'option allow_url_fopen activée, le "mieux à faire" c'est d'utiliser le file_get_content et file_put_content
file_put_contents($fichier, file_get_contents($url));
Concrètement, ça revient à appeler les fonctions fopen(), fwrite() et fclose() tour a tour, c'est dans la doc ! Donc c'est plus court et dieu sait que plus c'est court, plus on se sent bien (ça c'est pas écrit^^).
Commandes Exec()
Sinon il y a aussi les commandes via la fonction php exec() qui va directement effectuer le plus gros du boulot comme on pourrait le faire dans un terminal avec wget .
$rep_temp = $_SERVER['DOCUMENT_ROOT'].'/temp'; exec("cd $rep_temp && wget --quiet $url"); if (!file_exists($rep_temp.'/son_image.jpg')) { throw new Exception("Erreur de téléchargement de l'image"); } if (rename($rep_temp.'/son_image.jpg', $fichier) === false) { throw new Exception('Plantage en passant le fichier du rep temp au rep final'); }
Si jamais le serveur renvoie une erreur HTTP 404 ou 403, le fichier en sortie sera créé quand même mais il sera vide. Donc pour utiliser ce genre de méthodes, il faut effectuer un minimum de vérifications sur l'existence du fichier et des permissions nécessaires etc.
Utiliser CURL
En deux mots, la bibliothèque cURL sert à communiquer facilement avec les serveurs en parlant le même langage qu'eux. Ce langage est défini par ce qu'on appelle un protocole. L'extension cURL permet donc d'interagir en PHP avec tous ces protocoles que nous employons de manière quotidienne sans avoir à gérer leur connexion et sans penser à la manière d'écrire la requête ou de recevoir la réponse.
Voici la méthode la plus sure selon moi pour faire le boulot le plus proprement possible. cURL est a la fois super simple et super souple et sa capacité à prendre en charge les differents protocoles m'a personellement convaincu.
$ch = curl_init($url); $fp = fopen($fichier, 'wb'); curl_setopt($ch, CURLOPT_FILE, $fp); curl_setopt($ch, CURLOPT_HEADER, 0); curl_exec($ch); curl_close($ch); fclose($fp);
Cette extension est vraiment très puissant et très complète alors en fait, le mieux c'est d'aller dans la doc pour en savoir plus, ca vaut le coup. Et pour ceux qui n'ont pas la chance de pouvoir l'utiliser (information que vous pouvez obtenir via votre sortie de phpinfo), vous devrez vous tourner vers des alternatives comme fsockopen ou plus simplement vers les traditionnelles fonctions de lecture de fichiers comme file_get_contents et fopen, fread/fwrite, fclose comme on a vu au dessus.
Il faut quand meme penser a passer la directive allow_url_fopen à On et ca roule.
Voila, maintenant, avec un petit script qui comparera les versions distantes et celles de votre serveur, vous pourrez lancer le téléchargement de la collection de photos de médor, le chien de madame michu... Et ca, ca n'a pas de prix !
Retour a la liste