[PHP] Sauvegarder une image distante en local en utilisant cURL

Rate this post

Depuis quelques jours, je me suis remis à développer quelques fonctionnalités supplémentaires pour Websourcing. J’ai notamment tenté de résoudre de vieux problèmes de performances.
L’un d’entre eux est la résolution DNS de trop nombreux nom de domaines, parfois pour une seule ressource à télécharger. C’est par exemple le cas pour les images de « l’égotron » en bas à droite.

Ces images sont systématiquement récupérées sur les site en question, alors qu’elles ne changent, au mieux, qu’une fois par mois (le classement Wikio et Blogonet ne sont remis à jour qu’une fois par mois). Il en est de même pour les avatars provenant de Gravatar (quoi que dans ce cas un vrai cache est mis en place, mais reste la résolution DNS) qui sont rarement mis à jour.

L’idée que j’ai tenté de mettre en place est de sauvegarder localement les images, et de faire en sorte que celles-ci soit remise à jour, soit à la demande, via l’administration WordPress, soit automatiquement, via WP-Cron.

En règle générale, ceci est facilement réalisable. On ouvre le fichier distant et on en crée une copie locale.

Par exemple :

$img = imagecreatefromjpeg('http://www.unsite.com/image.jpg');
$path="/wp-content/cache/images/";
imagejpeg($img, $path);

ou encore plus simple dans certains cas en utilisant le wrapper HTTP :

copy('http://www.unsite.com/image.jpg', '/tmp/file.jpg');

Super simple. Sauf que sur certains hébergements, l’appel à allow_url_fopen n’est pas permis et du coup le code ci-dessus ne fonctionne pas.
En fouillant un peu, j’ai trouvé une autre technique qui fonctionne beaucoup plus souvent (quasiment de partout). Celle-ci se base sur la lib cURL:

function local_image($img,$fullpath){
$ci = curl_init ($img);

curl_setopt($ci, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ci, CURLOPT_HEADER, 0);
curl_setopt($ci, CURLOPT_BINARYTRANSFER,1);
	
$data=curl_exec($ci);

curl_close ($ci);

if(file_exists($fullpath)){
  unlink($fullpath);
}

$fp = fopen($fullpath,'x');
fwrite($fp, $data);
fclose($fp);

}

Simple et fonctionnel comme solution. De quoi rapatrier en local toutes les vignettes que je crée à la volée et qui ont des paramètres de caching très courts (5 min).
Avec cette technique, il vous suffit alors de mettre l’adresse locale pour l’image.

Attention tout de même au pipelining des navigateurs, qui gère 6 à 8 fils par défaut sur un même domaine. Tout mettre sur le même domaine peut avoir l’effet inverse (mais c’est rare).