Se connecter avec
S'enregistrer | Connectez-vous

[info] [php] Forcer un téléchargement

Dernière réponse : dans Programmation
Expert Programmation

Il est parfois intéressant ou nécessaire de forcer le téléchargement d'un fichier. Rien d'indélicat ou de sournois dans le principe. :jap: 

Un ex. qui devrait parler à Johann & Pirlouit : il est parfois préférable de pouvoir télécharger un document pdf plutôt que de le voir s'ouvrir dans son navigateur. C'est intéressant quand le pdf est de grosse taille, que la lecture du contenu n'est pas nécessaire dans l'immédiat, etc. Dans le cas qui m'intéressait aujourd'hui, le but était de laisser le choix au visiteur entre voir ou télécharger des pdf, et ce sans devoir utiliser le fastidieux menu contextuel (clic droit) pour les néophytes.

Quelques rapides recherches m'ont dirigé vers un code basé sur l'envoi de header http. Ce code permet d'afficher la fenêtre de téléchargement des navigateurs ; il peut ressembler à ceci :
  1. $fichier = 'monfichier';
  2. $chemin = 'telechargement/' . $fichier;
  3. if (file_exists($chemin))
  4. {
  5. header('Content-disposition: attachment; filename="' . $fichier . '"');
  6. header('Content-Type: application/force-download');
  7. header('Content-Transfer-Encoding: binary');
  8. header('Content-Length: '. filesize($chemin));
  9. header('Pragma: no-cache');
  10. header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
  11. header('Expires: 0');
  12. readfile($chemin);
  13. }
  14. else
  15. {
  16. $erreurFichier = 'le fichier "' . $fichier . '" n\'existe pas. Veuillez-nous excusez pour le désagrément.';
  17. }

On retrouve un code similaire à celui-ci un peu partout sur le Web. Il marche bien, pas de souci... du moins tant qu'on se contente de vraiment enregistrer le fichier cible.

Seulement voilà, les navigateurs proposent aussi d'ouvrir le fichier à télécharger (c'est les choix "ouvrir" du menu de téléchargement). Dans ce cas, le code marche toujours, sauf pour IE (comme par hasard diront les mauvaises langues ;)  ). Dans le cas d'un pdf par exemple, IE récupère bien le fichier, ouvre bien Adobe Reader, mais pas de bol, Reader affiche un message d'erreur comme quoi le fichier pdf n'existe pas :/ 

Il est en fait assez simple de remédier au problème, puisqu'il ne s'agissait que d'un Cache-control trop restrictif pour IE. Il faut supprimer les option "no-cache" et "no-store". On obtient au final ce code qui marche même pour l'option "ouvrir" de d'Internet Explorer :
  1. $fichier = 'monfichier';
  2. $chemin = 'telechargement/' . $fichier;
  3. if (file_exists($chemin))
  4. {
  5. header('Content-disposition: attachment; filename="' . $fichier . '"');
  6. header('Content-Type: application/force-download');
  7. header('Content-Transfer-Encoding: binary');
  8. header('Content-Length: '. filesize($chemin));
  9. header('Pragma: no-cache');
  10. header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
  11. header('Expires: 0');
  12. readfile($chemin);
  13. }
  14. else
  15. {
  16. $erreurFichier = 'le fichier "' . $fichier . '" n\'existe pas. Veuillez-nous excusez pour le désagrément.';
  17. }

En espérant que ça puisse servir à quelques uns :) 

Autres pages sur : info php forcer telechargement

Lassé par la pub ? Créez un compte

Salut,

Ce script est top pour faire du force-download de fichiers locaux qu'on a sur son serveur.

Le pb c'est que j'essaye de faire du force-download à partir d'une page de mon site, mais qui téléchargerait une page sur un site qui n'est pas à moi (le fichier est énorme et je ne veut pas le mettre sur mon serveur).

Or qd je remplace :
readfile(fichier local );
par
readfile(http://cheminversfichierdistant);

ca ne marche pas. Quelqu'un peut m'aider ?

Merci !!

A+

David
Expert Programmation

simple : c'est une mauvaise idée.

c'est une mauvaise idée du point de vue technique car le traffic va passer du serveur distant à ton serveur puis au client. si l'autre serveur est pas sur le même réseau alors la lenteur du téléchargement risque d'augmenter et tu va gaspiller de la bande passante. et de plus tu pourrai faire un effort et ne pas linker à l'arrache les fichiers d'un autre site ;)  ...

le mieux c'est de faire ça sur l'autre serveur.

Merci aussi, ca m'a permis de corriger un problème sous IE6 (encore lui !) quand on faisait "ouvrir".

Tout le reste marchait bien : "Enregistrer" sous IE6 et "Ouvrir" ou "Enregistrer" sous Firefox.

J'attends de voir si ca marche bien sous Mac, et aussi sur les versions de IE plus récente (7 et 8)

Expert Programmation

:pfff:  On s'en cogne de savoir le nom du fichier et son chemin complet.
Par contre, nous donner le contenu du fichier aux alentours de la ligne 13, c'eut été un peu plus intelligent.

Bonjour

J'ai juste copier la totalité du message d'erreur ... tout le monde ne sait pas qu'il n'est pas utile de procéder comme ça... de plus je ne maîtrise absolument pas le PHP ....

Enfin si j'ai mis le lien du site , c'est juste pour permettre de voir où ça pêche ... l'idée de "pub" n'est pas présente dans mon esprit sur des forum de PHP ect ... pour ça j'ai d'autres moyens.

Ca c'est pour la réponse que je trouve quelque peu "agressive"

enfin pour répondre à ta question je n'ai pas copié le code car il est dans le message de "marsien" mais je veux bien le recopier si ça peut t'éviter de lire son message entier

Code :

1.$fichier = 'monfichier';
2.$chemin = 'telechargement/' . $fichier;
3.if (file_exists($chemin))
4.{
5. header('Content-disposition: attachment; filename="' . $fichier . '"');
6. header('Content-Type: application/force-download');
7. header('Content-Transfer-Encoding: binary');
8. header('Content-Length: '. filesize($chemin));
9. header('Pragma: no-cache');
10. header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
11. header('Expires: 0');
12. readfile($chemin);
13.}
14.else
15.{
16. $erreurFichier = 'le fichier "' . $fichier . '" n\'existe pas. Veuillez-nous excusez pour le désagrément.';
17.}
Expert Programmation

Bonjour,

Ce que tu prends pour de l'agressivité n'est que le reflet de ma lassitude par rapport à des gens qui s'imaginent qu'on peut user et abuser de la bonne volonté des membres des forum sans faire soi-même un petit effort. De plus, lire le règlement du forum par exemple, et le respecter est la politesse minimum sur un forum. En le lisant, tu y apprendras que le code se publie ici sous certaines conditions de mise en forme.

---------------------------------------

La ligne 13 de ton extrait de code ne contient pas de variable, je doute qu'il y ait correspondance exacte entre ton fichier et cet extrait. Il faudrait nous dire à quelle ligne de cet extrait correspond l'erreur PHP.

Bon, il est possible aussi que tu ais une bête faute de frappe à la ligne 12 (13-1). Vérifie bien ton code.

(Utilise la fonction Edition pour virer le saimal.fr de ton message. N'en profite pas pour y remettre de la "pub"; N'hésite pas à mettre un lien vers ton site dans ta signature ;)  )
Lassé par la pub ? Créez un compte