Provoquer un téléchargement d'image

Eléphant du PHP | 109 Messages

18 avr. 2010, 21:00

Bonjour à tous,

voila, je souhaiterais pouvoir "provoquer" un téléchargement. Je m'explique :
- L'utilisateur clique sur un lien
- Le lien dirige l'utilisateur sur la page download.php
- la page download.php provoque le téléchargement de l'image

Assez simple allez vous me dire. Je le pensais aussi. Seulement arrivé à la dernière étape, l'image ne fait que s'afficher. :(
J'ai donc demandé à Google. Résultat : la fonction readfile() correspondrait à mes besoins. J'ai lu le manuel, fait quelques tests, malheureusement tous aussi vains que les autres.


Du concret :


Je vous épargne la page avec le lien, vous n'en aurez pas besoin. Sachez seulement que je vais l'appeler, par exemple, lien.htm

La page download.php vers laquelle le lien de la page lien.htm dirige l'utilisateur :
<?php
$file = $_GET['file']; // Exemple de $file : http://www.google.fr/intl/fr_fr/images/logo.gif (un url quoi...)

if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
    readfile($file);
   
}


?>
J'ai par exemple essayé de modifier le header content-type : image/jpeg et d'autre choses dans le style, mais l'image ne fait que s'afficher encore une fois. :cry:

Quand j'arrive sur cette page, cela me provoque bien un téléchargement mais l'image est inutilisable et illisible. :(

Question :

- Comment faire pour que, tout en conservant ce que je nomme "téléchargement", l'image reste lisible et pleinement utilisable lorsque l'utilisateur l'a sur son disque?


Merci d'avance et bonne fin de journée à tous ;) (et aussi fin des vacances de Pâques pour moi :( )


EDIT :

En Googlant les bons termes ("forcer le téléchargement"), j'ai trouvé un bout de script qui m'a aidé. Cependant, mon problème n'est pas résolu :(

Les script :
<?php
$file = $_GET['file'];

if (file_exists($file)) {


    switch (strrchr(basename($file), ".")) {

    case ".png": $type = "image/png"; break;
    case ".gif": $type = "image/gif"; break;
    case ".jpg": $type = "image/jpeg"; break;
    case ".PNG": $type = "image/png"; break;
    case ".GIF": $type = "image/gif"; break;
    case ".JPG": $type = "image/jpeg"; break;
    case ".JPEG": $type = "image/jpeg"; break;
    case ".jpeg": $type = "image/jpeg"; break;
    }
    
    header('Content-Description: File Transfer');
    header("Content-Type: $type");
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
    readfile($file);
    echo "Salut !";
   
}


?>

Visiblement le file_exists retourne false vu que le Salut ! ne s'écrit pas.
Si je vire ce test, le fichier ce télécharge comme je le veux, mais est encore illisible. #-o
ANSI <font> <font> <font> <li> <p> <title> Mar I/O .NET

devlop78
Invité n'ayant pas de compte PHPfrance

18 avr. 2010, 23:02

Ca ... faut surtout pas écrire Salut ...

Moi j'ai utilisé pour un fichier ISO-8859-1 cela :

Code : Tout sélectionner

header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename='.basename($file)); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header('Content-Length: ' . filesize($file)); ob_clean(); flush(); readfile($file); exit;
Je vais faire le test pour une image et je te tiens au courant

devlop78
Invité n'ayant pas de compte PHPfrance

18 avr. 2010, 23:03

<?php
$file = 'planete.png';
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;

?>

fonctionne très bien chez moi ...

devlop78
Invité n'ayant pas de compte PHPfrance

18 avr. 2010, 23:17

$file = $_GET['file']; // Exemple de $file : http://www.google.fr/intl/fr_fr/images/logo.gif (un url quoi...)
Pas de URL distante avec file_exists, il n'en voudra pas ... fais un test avec une image dans le même répertoire que ton script et ensuite vois quelle est la meilleure façon de lire ton image ...
Vous pouvez utiliser une URL comme nom de fichier avec cette fonction, si le gestionnaire fopen a été activée
(http://php.net/manual/fr/function.readfile.php)

Eléphant du PHP | 109 Messages

19 avr. 2010, 18:54

Bonjour,

je viens de donner un petit coup de ini_get sur "allow_url_fopen", il m'a retourné true.
Donc le gestionnaire fopen est activé. Je suis donc en mesure de faire readfile($urlDistant); ? (arrête moi si je me trompe)

De toute façon, je viens de retester ce code avec une image disponible sur mon serveur. L'image se DL bien, elle passe le test de file_exist mais est illisible...
La preuve en image : (c'est le cas de le dire :lol: )
Image

Le code que j'ai utilisé :
<?php
if (file_exists('../upload/images/test.png')) {

      header('Content-Description: File Transfer');
      header('Content-Type: application/octet-stream');
      header('Content-Disposition: attachment; filename='.basename('../upload/images/test.png'));
      header('Content-Transfer-Encoding: binary');
      header('Expires: 0');
      header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
      header('Pragma: public');
      header('Content-Length: ' . filesize('../upload/images/test.png'));
      ob_clean();
      flush();
      readfile('../upload/images/test.png');
     
   
}
?>
Mmh, what happen? :shock:
Merci encore ;)
ANSI <font> <font> <font> <li> <p> <title> Mar I/O .NET

ViPHP
ViPHP | 5462 Messages

19 avr. 2010, 18:57

      ob_clean();
      flush();
ca sert a rien


tout les header aussi (sauf si tu veux du particulier)
header("Content-Type: application/force-download");
header("Content-Disposition: attachment; filename=$file");
readfile($file);

Eléphant du PHP | 109 Messages

19 avr. 2010, 19:52

      ob_clean();
      flush();
ca sert a rien
(...)
C'est possible, c'est le script que j'avais trouvé sur la page de manuel de readfile. (http://php.net/manual/fr/function.readfile.php)

Quant a mon problème, il est résolu :)
C'est le fait d'avoir remplacer ceci :
header('Content-Type: application/octet-stream');
Par ceci :
header("Content-type: application/force-download"); 
Merci à vous deux. :)
ANSI <font> <font> <font> <li> <p> <title> Mar I/O .NET

devlop78
Invité n'ayant pas de compte PHPfrance

19 avr. 2010, 22:33

De rien ... le code était le même pour moi, on a dû le trouver au même endroit ... après les headers indispensables ou non je ne sais pas. J'avais prévu de me pencher là-dessus mais je ne l'ai pas encore fait ...

Tu utilises quel OS et quel navigateur ? Cela peut être intéressant que je revois mon code si il ne fonctionne pas partout ... (moi c'est pas une image mais du code html, mais ce n'est pas une raison ...)

devlop78
Invité n'ayant pas de compte PHPfrance

19 avr. 2010, 22:34

De rien ... le code était le même pour moi, on a dû le trouver au même endroit ... après les headers indispensables ou non je ne sais pas. J'avais prévu de me pencher là-dessus mais je ne l'ai pas encore fait ...

Tu utilises quel OS et quel navigateur ? Cela peut être intéressant que je revois mon code si il ne fonctionne pas partout ... (moi c'est pas une image mais du code html, mais ce n'est pas une raison ...)

ViPHP
ViPHP | 5462 Messages

19 avr. 2010, 22:37

ouais dans la doc, les exemples sont pas terrible des fois...
après force-download ca porte bien sont non ca doit obligé le navigateur a ouvrir une fenêtre de téléchargement même si il est dans la capacité d'afficher le type de MIME

Eléphant du PHP | 109 Messages

20 avr. 2010, 21:13

Bonjour,

encore une fois mieux vaut tard que jamais ;)
Pour ma part je suis sous Ubuntu avec chrome. J'avais quand même testé ce code sous Firefox et ça fonctionne à mervielle.

Une chose m'intrigue, l'ancien code avec "octets / stream" te donnais une image valide?
Avais tu essayé de l'ouvrir?

Bonne soirée ;)
ANSI <font> <font> <font> <li> <p> <title> Mar I/O .NET