Forcer le téléchargement d’un fichier (PHP/.htaccess)

11 01 2012

Par défaut, quand vous chargez une URL dans la barre d’adresse d’un navigateur (Firefox, Safari, Chrome…), celui-ci adopte un comportement différent en fonction du type de fichier.

Si c’est une page web, une image ou un fichier texte par exemple, le navigateur va afficher le contenu de ce fichier dans sa fenêtre.

Par contre si c’est un fichier dont le type n’est pas pris en charge nativement par le navigateur (exemple : fichier excel, fichier Photoshop, ZIP, exécutable…), alors il va télécharger le fichier.

Parfois, on souhaite que le navigateur propose toujours le téléchargement, même pour les types pris en charge.

Pour cela, il faut que le serveur envoi des headers HTTP spécifiques qui vont indiquer au navigateur de toujours télécharger, on appelle ça le force download.

Sur un serveur Apache/PHP, il y a 2 façons de le faire :

Force download en PHP

L’idée est extrêmement simple : on balance les headers et ensuite on envoie le contenu du ficher avec la fonction readfile().

<?php
$filename = "Votre_Fichier.ext";

# Envoi des entêtes HTTP qui permettent de forcer le téléchargement
header("Content-disposition: attachment; filename=".$filename);
header("Content-Type: application/force-download");
header("Content-Transfer-Encoding: application/octet-stream");
header("Content-Length: ".filesize($filename));
header("Pragma: no-cache");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0, public");
header("Expires: 0");

# Lecture & envoi du fichier au client (navigateur)
readfile($filename);
?>

Le header Content-Length est très important, c’est ce qui permettra au client de détecter la fin du téléchargement et aussi d’estimer le temps de téléchargement.

L’inconvénient de cette méthode, c’est que le script PHP continu de tourner pendant toute la durée du téléchargement, du coup on risque de se prendre une erreur max_execution_time.

Sans compter que si le script est merdique, il va consommer de la mémoire pour rien, voir bloquer les autres scripts (par exemple si vous n’avez pas libéré la session avec session_write_close(), ou encore si vous n’avez pas fermé une éventuelle connexion base de données).

C’est pour ça que je vais vous montrer une autre façon de le faire, plus propre.

Force download avec un .htaccess (Apache)

On peut faire la même chose directement avec Apache, via httpd.conf ou via un .htaccess, en utilisant les modules mod_headers et mod_mime :

ForceType application/octet-stream
Header set Content-Disposition attachment

Le seul petit problème est que si vous placez ça dans un htaccess, ces règles vont aussi s’appliquer au listing automatique de répertoires d’Apache (mod_autoindex).
Donc si vous accédez à http://monsite/mes-images/, vous aurez un téléchargement au lieu de l’affichage de la liste des fichiers du répertoire.

Heureusement, on peut facilement exclure le listing avec une directive FilesMatch :

<FilesMatch ".+">
    ForceType application/octet-stream
    Header set Content-Disposition attachment
</FilesMatch>

Et voilà ;)


Partager :

Ces icônes sont des liens vers des sites de partage de signet sociaux où les lecteurs peuvent partager et découvrir de nouveaux liens.
  • Digg
  • del.icio.us
  • Facebook
  • Digg -fr
  • Live
  • MisterWong Fr
  • Scoopeo
  • StumbleUpon
  • Technorati
  • Wikio FR

Actions

Informations

Et maintenant je fais quoi ?

Aucun commentaire

3 réponses à “Forcer le téléchargement d’un fichier (PHP/.htaccess)”

5 01 2018
art (16:22:10) :

I am in fact thankful to the holder of this web site who
has shared this fantastic post at at this place.

21 03 2018
kepago (06:32:53) :

If you desire to take much from this paragraph then you have to
apply these techniques to your won website.

22 06 2020
JesseFaw (13:30:33) :

Est-ce que quelqu’un a deja utilise les services de telemedecine de MaQuestionMedicale pour voir un medecin de garde? Pouvez-vous me donner votre avis?

Laisser un commentaire

Vous pouvez utiliser ces balises html : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>