Page 1 sur 1

Problème avec header et content-disposition

Posté : 25 juin 2013, 16:32
par MaeALT
Bonjour à toutes et à tous,

Je ne suis pas ce qu'on appelle experte en php donc je viens me renseigner auprès de vous : je dois actuellement générer un fichier csv depuis une appli web. Pour cela je suis le manuel php et le complète petit à petit.
Tout ne passe pas trop mal (j'obtiens ce que je veux, i.e aaa,bbb,ccc,dddd) jusqu'à ce que je rajoute la ligne suivante :

Code : Tout sélectionner

header('Content-Disposition: attachment; filename="download.csv"');
Là, je peux télécharger le fichier mais le contenu change : j'obtiens le aaa,bbb,ccc,dddd suivi de tout le code source de la page.
Je ne comprends pas ce comportement, quelqu'un peut-il m'aider?

Pour info, le code complet :

Code : Tout sélectionner

public function extract() { $list = array ( array('aaa', 'bbb', 'ccc', 'dddd'), array('123', '456', '789'), array('"aaa"', '"bbb"') ); $filename = "export_".date("Y.m.d").".csv"; $fp = fopen('file.csv', 'w'); header("Content-Type: application/csv"); header('Content-Disposition: attachment; filename="download.csv"'); foreach ($list as $fields) { fputcsv($fp, $fields, ';'); } fclose($fp); }

Re: Problème avec header et content-disposition

Posté : 25 juin 2013, 18:00
par moogli
salut,


la tu cré un fichier tu ne l'envoie pas au navigateur.

pour l'envoyer au navigateur il faut que tu "affiche" sont contenu.

dans ton cas je ferais ainsi
<?php
public function extract() {
    $list = array (
        array('aaa', 'bbb', 'ccc', 'dddd'),
        array('123', '456', '789'),
        array('"aaa"', '"bbb"')
    );

    $csv = 'colonne1; colonne 2; colonne 3; colonne 4';
    foreach ($list as $fields) {
        $csv .= implode(';',$fields).PHP_EOL;
    }
    $filename = "export_".date("Y.m.d").".csv";
    
    header("Cache-Control: no-cahe, must-revalidate");
    header("Content-Type: application/csv");
    header('Content-Disposition: attachment; filename="'.$filename.'csv"');
    header('Expires: 0');
    header('Content-Length: ' . strlen($csv));
    
    echo $csv;
}

@+

Re: Problème avec header et content-disposition

Posté : 26 juin 2013, 09:15
par MaeALT
Je vous remercie pour le code fourni !
Malheureusement, le résultat reste équivalent : j'ai bien la list avec le nom des colonnes mais ensuite (après le fichier que je veux) il y a toujours le code source.
Faudrait-il mettre un EndOfFile qqpart pour bloquer l'écriture?

Re: Problème avec header et content-disposition

Posté : 26 juin 2013, 09:30
par Mazarini
Si une partie du code php n'est pas interprété, c'est qu'il y a un problème avec les ouvertures/fermetures de balises php : <?PHP et ?>.
Le premier bout de code PHP qui apparaît doit te permettre de trouver ou manque une balise <?PHP ou bien ou il y a une balise ?> en trop.

Re: Problème avec header et content-disposition

Posté : 26 juin 2013, 13:20
par moogli
Comment utilise tu cette méthode ?

@+

Re: Problème avec header et content-disposition

Posté : 27 juin 2013, 09:19
par MaeALT
Mazarini : je ne pense pas que du code php ne soit pas interprêté puisque je retrouve dans le document généré ce que j'attends. Mais cela est suivi du code source. Par ailleurs, si je fais un fopen('file.csv', 'w') sans mettre le content-disposition, je retrouve le fichier dans webroot et il contient ce que je veux. C'est ce qui m'intrigue le plus !

Moogli :
Pour mes tests (car j'ai besoin d'y aller à petits pas étant donné que ça ne fonctionne pas et que je souhaite comprendre l'intérêt de chaque ligne), j'ai juste un lien sur une page qui redirige vers l'action extract (du controller) dans laquelle est mis le code. Il y a également une vue (si je ne met pas content-disposition, ça m'amène à la vue et créé le fichier dans webroot).

Merci d'essayer de m'aider, j'espère que nous y arriverons :)

Re: Problème avec header et content-disposition

Posté : 27 juin 2013, 09:45
par Mazarini
Je dis juste qu'une partie du php n'est pas interprété. Si tu la voie du php dans le source html, c'est ce que ca signifie.

Les headers indiquent ce que tu vas envoyer au navigateur : le type de fichier, le nom du fichier...
L'attachement permet d'indiquer que tu envoies un fichier et alors la page n'est pas reconstruite, juste le fichier recu. L'envoi du header ne prend pas en charge l'envoi du fichier.

Si tu crées un fichier par fopen(), il faut quand même l'envoyer avec un echo du contenu ou un readfile().

Re: Problème avec header et content-disposition

Posté : 27 juin 2013, 15:12
par MaeALT
Je pense que nous nous sommes mal compris.
Je n'ai pas de code php dans mon code source (quand j'ai débuté il y a qq semaines, j'avais rencontré ce problème).
Voici le fichier que je voudrais obtenir :

Code : Tout sélectionner

aaa;bbb;ccc;dddd 123;456;789 """aaa""";"""bbb"""
Et voici ce que j'obtiens avec attachment :

Code : Tout sélectionner

<!DOCTYPE html> <html> <head> ... </head> <body> ... </body> </html>
La seule différence entre les deux codes est la ligne
header('Content-Disposition: attachment; filename="download.csv"');
Je n'ai même pas de echo du contenu (je ne sais pas comment ça marche, je ne savais pas qu'il fallait faire ça).

Re: Problème avec header et content-disposition

Posté : 27 juin 2013, 15:40
par Mazarini
Qu'est devenu la fonction par rapport à ce que tu nous as montré dans le premier post ?
Comment est appelé la fonction extract() ?

D'ailleurs, "extract" n'est pas une bonne idée, cf http://php.net/manual/fr/function.extract.php.

Une seule chose peut être envoyée par un script PHP : un download ou une page html, mais pas les 2 ensemble. Pour déclencher l'affichage d'une nouvelle page et l'envoi du fichier, il faut passer par du javascript pour appeler 2 scripts. A priori en ouvrant une fenêtre du navigateur ou via de l'ajax ; mais ce genre de truc n'est pas mon fort.

Re: Problème avec header et content-disposition

Posté : 27 juin 2013, 16:12
par MaeALT
Actuellement, ma fonction ressemble à ça (je viens de changer le nom, suivant tes conseils avisés) :
public function extraction() {
        
         $list = array (
            array('aaa', 'bbb', 'ccc', 'dddd'),
            array('123', '456', '789'),
            array('"aaa"', '"bbb"')
         );
         $fp = fopen('file.csv', 'w');
    header("Content-Type: application/csv");
    //header('Content-Disposition: attachment; filename="download.csv"');

         foreach ($list as $fields) {
             fputcsv($fp, $fields, ';');
         }

         fclose($fp);
    }
Si je décommente la ligne, c'est là où se pose le problème.

Par contre, je ne savais pas qu'on ne pouvait envoyer qu'une seule chose en php. Le problème doit alors venir de là, peut-être qu'il essaye d'envoyer les deux (download et html) dans le fichier que je spécifie.
Mais comme toi, javascript reste obscure pour moi. Je peux peut-être mais du code dans un helper? (c'est peut-être une très mauvaise idée, je ne me rends pas compte, désolée pour ceux que j'offense ^^ )

Re: Problème avec header et content-disposition

Posté : 27 juin 2013, 16:25
par Mazarini
Il faudrait que tu essayes avec une page de test :
<?php
    $list = array (
        array('aaa', 'bbb', 'ccc', 'dddd'),
        array('123', '456', '789'),
        array('"aaa"', '"bbb"')
    );

    $csv = 'colonne1; colonne 2; colonne 3; colonne 4';
    foreach ($list as $fields) {
        $csv .= implode(';',$fields).PHP_EOL;
    }
    $filename = "export_".date("Y.m.d").".csv";
    
    header("Cache-Control: no-cache, must-revalidate");
    header("Content-Type: application/csv");
    header('Content-Disposition: attachment; filename="'.$filename.'csv"');
    header('Expires: 0');
    header('Content-Length: ' . strlen($csv));
    
    echo $csv;
?>
(j'ai juste repris le code de Moogli et viré la fonction (ou méthode)

Tu pourras ensuite faire une petite page html avec juste un lien vers ce script. Je pense que ca va éclaircir la situation.
Si ca marche avec la page html enlève l'attachement pour voir la différence.

Re: Problème avec header et content-disposition

Posté : 01 juil. 2013, 13:56
par MaeALT
Merci pour ton idée ! (J'ai été prise sur une autre fonctionnalité ces derniers jours donc je n'avais pas eu le temps de m'y mettre).
J'ai mis ce code dans la page d'extraction (je ne sais pas si c'est ce que tu voulais dire) et ça m'affiche le texte mais aucun téléchargement n'est proposé. Je vais m'y replonger l'après-midi mais je rame. Peut-être devrais-je repartir de zéro même si là je n'ai qu'un code simpliste, ça ne passe quand même pas.

Merci pour votre aide, je vous tiens au courant des éventuels problèmes et de la solution (si je trouve ^^).

Edit : Je viens de me rendre compte que le fichier télécharger est de la forme : nom.csv.htm
Mais d'où peut venir cette fichue 2ème extension?

Re: Problème avec header et content-disposition

Posté : 01 juil. 2013, 23:51
par moogli
comment propose tu le téléchargement et comment fait tu (avec le navigateur) pour enregistrer ?


@+

Re: Problème avec header et content-disposition

Posté : 02 juil. 2013, 09:33
par MaeALT
J'ai une page avec un lien pour exporter. Ce lien mène à une autre page dédié à l'export. Peut-être est-ce là mon erreur?
Je pourrais mettre un lien qui ne mène pas à une autre page et proposant un téléchargement? (je ne vois pas comment faire pour le moment)
Ensuite, la boîte de téléchargement "typique" de firefox s'affiche me proposant d'enregistrer le fichier :
"matrice.csv qui est un fichier de type : Firefox HTML Document"

Je viens de voir que sous Chrome, il m'enregistre bien un csv. Mais le contenu est le même par contre.

Re: Problème avec header et content-disposition

Posté : 02 juil. 2013, 13:54
par MaeALT
Résolu : il est nécessaire de mettre un exit() à la fin de la méthode d'export du controller, tout simplement (mais encore faut-il le savoir).
Merci de m'avoir aidé et permis de ne pas me décourager :)