Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 01-04-2010 15:56:07

lefafa
Membre
Date d'inscription: 03-03-2010
Messages: 13

[Résolu] Exporter des données en fichier CSV

bonjour à tous,

Dans mon application j'aurai besoin d'une fonctionnalité d'export de données en CSV :

l'utilisateur clique sur un lien "exporter" et le navigateur doit lui proposer le téléchargement d'un fichier CSV contenant les données d'une table de la base de données. Et ceci pour quasiment chaque table de ma base.

Le problème est que je ne vois pas du tout comment procéder.
Dois-je créer une aide d'action, ZF propose-t-il cette fonctionnalité d'export ? pour l'instant j'avoue être un peu perdu.

Dernière modification par lefafa (07-04-2010 14:16:13)

Hors ligne

 

#2 01-04-2010 16:17:44

Godzinho
Membre
Lieu: Toulouse
Date d'inscription: 15-10-2009
Messages: 58

Re: [Résolu] Exporter des données en fichier CSV

Salut,

je me suis penché sur ce problème la semaine dernière.

Pour ma part j'ai créé une action dans un de mes contrôleurs. Voici comment j'ai procédé :
- création du fichier destination avec fopen
- insertion d'une ligne de titre de colonne avec la fonction fputcsv si besoin
- parcours du tableau de données puis insertion de chaque ligne avec fputcsv
- fermeture du fichier avec fclose
- insertion des headers qui vont bien
- lecture du fichier généré avec la fonction readfile
- désactiver le renderer de ton action ainsi que le layout

Maintenant, si au travers d'un lien tu fais appel à cette action, tu devrais avoir une fenêtre te permettant d'ouvrir ou d'enregistrer le fichier csv.

N'hésite pas pour plus d'infos.

Hors ligne

 

#3 01-04-2010 16:36:05

sekaijin
Membre
Date d'inscription: 17-08-2007
Messages: 1137

Re: [Résolu] Exporter des données en fichier CSV

bonjour

pas une réponse directe à ce sujet mais quelque chose qui le touche de loin
une classe pour parser les fichiers csv qui prend en compte le fait qu'un champ peut contenir un séparateur (de champs ou de fin de ligne s'il est délimité

Code:

<?php
/**
 * Lecture de fichier CVS prenant en compte le fait qu'un séparateur peut êtr eprésent dans un champs s'il est délimité.
 *
 * @package Fast
 * @copyright  ftgroup
 * @author Jean-Yves Terrien
 * @package  Fast_CVS
 */


/* sample
   $cvs = new Fast_Csv_Parser('file.csv');
   $row = $cvs->getRow();
   while (!$cvs->eof()) {
      print_r($row);
      $row = $cvs->getRow();
   }
   $cvs->close();

 */ 
class Fast_Csv_Parser {
   /**
    * @param string $filename nom du fichier à parser
    * @param string $separator column separator char
    * @param string $enclosure column enclosure char
    */
   public function __construct($filename, $separator = ';',$enclosure='"') {
      $this->separator =$separator;
      $this->enclosure =$enclosure;
      $this->filename = $filename;
      $this->resource = fopen($filename,'r');
   }

   // replace double enclosure mark by single enclosure mark
   function cleanField($field) {
      return preg_replace('/'.$this->enclosure.$this->enclosure.'/', $this->enclosure, $field);
   }

   // Verify if is not truncated field
   function isCompletField(&$field) {
      if (($this->enclosure == substr($field, 0, 1)) &&
          ($this->enclosure == substr($field, -1, 1)) &&
          (0 == substr_count($field, $this->enclosure)%2))
      {
         $field = substr($field, 1, -1);
      }
      return (0 == substr_count($field, $this->enclosure)%2); //nombre pair de $this->enclosure
   }

   // get next row in cvs file
   public function getRow() {
      $line = $this->getLine();
      if (null != $line) {
         $this->row = array();
         $complete = false;
         $incompletField = false;
         //while incomplet row and not eof
         while (!$complete && null != $line) { 
            $list = explode ($this->separator, $line);
            foreach ($list as $key=>$value) {
               $value = trim($value,"\r\n");
               // if have an incomplet fiel try to complet it
               if ($incompletField) {
                  $value = $incompletField . $break . $value; 
               }
               if ($this->isCompletField($value)) //nombre pair de $this->enclosure
               {
                  $complete = ($key == count($list)-1); 
                  $this->row[] = $this->cleanField($value);
                  $incompletField = false;
               } else {
                  $incompletField = $value;
                  $break = $this->separator;
               }
            }
            if (!$complete && ($key == count($list)-1)) {
               $line = $this->getLine();
               $break = "\n";
            }      
         }
      } else {
         $this->row = null;
      
      }
      return $this->row;
   }

   // is end of file ?
   public function eof()
   {
      return (null === $this->row);
   }

   // close cvs file
   public function close () {
      if ($this->resource) {
         fclose($this->resource);
      }
   }

   public function getLine() {
      $line = null;
      if ($this->resource) {
         $line = fgets($this->resource);
      }
      return $line;
   }
}

a+jyt

Hors ligne

 

#4 01-04-2010 16:37:43

ndesaleux
Membre
Date d'inscription: 16-04-2007
Messages: 196
Site web

Re: [Résolu] Exporter des données en fichier CSV

Personnellement j'utiliserai plus l'helper ContextSwitch

http://framework.zend.com/manual/fr/zen … textswitch

Hors ligne

 

#5 01-04-2010 16:58:10

lefafa
Membre
Date d'inscription: 03-03-2010
Messages: 13

Re: [Résolu] Exporter des données en fichier CSV

merci à tous pour vos réponses rapides

Pour la création du fichier CSV ça fonctionne. J'ai bien un fichier temporaire dans mon répertoire contenant les données de ma table et parfaitement formaté.

Par contre lorsque le navigateur me demande de l'ouvrir ou de l'enregistrer (grâce à readfile) j'obtiens un fichier corrompu qui n'est même plus un csv et qui contient du code de mon layout !

@Godzinho : je pense que ça vient de mes headers, pourrais-tu me montrer lesquels tu utilises STP.

Dernière modification par lefafa (01-04-2010 16:58:40)

Hors ligne

 

#6 01-04-2010 18:24:51

sekaijin
Membre
Date d'inscription: 17-08-2007
Messages: 1137

Re: [Résolu] Exporter des données en fichier CSV

il faut désactiver le rendu

A+JYT

Hors ligne

 

#7 02-04-2010 07:59:52

Godzinho
Membre
Lieu: Toulouse
Date d'inscription: 15-10-2009
Messages: 58

Re: [Résolu] Exporter des données en fichier CSV

Salut,

effectivement il faut d'une part désactiver le rendu mais j'ai du également désactiver le layout principal pour éviter d'avoir le code html du layout dans mon fichier csv lorsque je l'ouvrais alors que le fichier seul était bel et bien généré.

Voici mon code :

Code:

     Zend_Layout::resetMvcInstance();
        
     $this->_helper->viewRenderer->setNoRender(true);

Et voici mes headers :

Code:

     header('Content-Type: text/csv');   
     header('Content-disposition: attachment; filename='. $nomFichier);

Dernière modification par Godzinho (02-04-2010 08:01:38)

Hors ligne

 

#8 02-04-2010 09:12:27

sekaijin
Membre
Date d'inscription: 17-08-2007
Messages: 1137

Re: [Résolu] Exporter des données en fichier CSV

j'ai eu un petit pb avec IE
voici les hedaer que j'utilise

Code:

            $this->getResponse()->setHeader('Pragma' , 'public', true);
            $this->getResponse()->setHeader('Cache-Control', 'max-age=0', true);
            $this->getResponse()->setHeader('Content-Type', 'application/javascript; charset=iso-8859-1; name="' . $data->site_name . '.txt"', true);
            $this->getResponse()->setHeader('Content-Transfer-Encoding', 'binary', true);
            $this->getResponse()->setHeader('Content-disposition', 'attachment; filename="'.$data->site_name.'.txt"', true);

mieux vaut utiliser setHeader de ZF que header
en effet header envois imédiatement le header au client alors que setHeader prépare tous les headers qui seront envoyé avant le rendu

du coup si dans un script (appel de fonction etc..) un même header est positioné avec des valeur différentes seul le dernier est envoyé alors qu'avec header ce sera le premier

A+JYT

Dernière modification par sekaijin (02-04-2010 09:19:05)

Hors ligne

 

#9 02-04-2010 09:28:26

Godzinho
Membre
Lieu: Toulouse
Date d'inscription: 15-10-2009
Messages: 58

Re: [Résolu] Exporter des données en fichier CSV

Je viens d'essayer de changer mon appel à la fonction header php par un appel via le ZF, mais lorsque je veux ouvrir mon fichier excel, il ne sait pas que c'est un fichier csv et je n'ai pas le nom voulu.

Hors ligne

 

#10 02-04-2010 10:11:25

lefafa
Membre
Date d'inscription: 03-03-2010
Messages: 13

Re: [Résolu] Exporter des données en fichier CSV

Encore merci à tous
grâce à vous j'ai enfin réussi à faire fonctionner mon export CSV

je vous donne le code :

Code:

$this->_helper->viewRenderer->setNoRender(true);
$this->_helper->layout->disableLayout();

//on récupère les données à insérer puis formatage pour le csv
//....

$fichier = fopen("/tmp/nom_fichier.csv", "w+");
fwrite($fichier, utf8_decode($data));
fclose($fichier);
        
header("Content-Type: application/csv-tab-delimited-table");
header("Content-disposition: filename=nom_fichier.csv");
readfile("/tmp/nom_fichier.csv");
unlink("/tmp/nom_fichier.csv");

Hors ligne

 

#11 02-04-2010 10:29:21

Godzinho
Membre
Lieu: Toulouse
Date d'inscription: 15-10-2009
Messages: 58

Re: [Résolu] Exporter des données en fichier CSV

De rien lefafa et merci pour le disableLayout() que je n'avais pas touvé.

Hors ligne

 

#12 02-04-2010 11:36:23

nORKy
Membre
Date d'inscription: 06-03-2008
Messages: 1098

Re: [Résolu] Exporter des données en fichier CSV

Perso, j'aurais aussi utilisé comme "ndesaleux" contextSwitch, qui se charge tout seul de desactiver le rendu, placé les entetes, ...


----
Gruiiik !

Hors ligne

 

#13 03-04-2010 11:22:56

sekaijin
Membre
Date d'inscription: 17-08-2007
Messages: 1137

Re: [Résolu] Exporter des données en fichier CSV

lefafa a écrit:

Encore merci à tous
grâce à vous j'ai enfin réussi à faire fonctionner mon export CSV

je vous donne le code :

Code:

$this->_helper->viewRenderer->setNoRender(true);
$this->_helper->layout->disableLayout();

//on récupère les données à insérer puis formatage pour le csv
//....

$fichier = fopen("/tmp/nom_fichier.csv", "w+");
fwrite($fichier, utf8_decode($data));
fclose($fichier);
        
header("Content-Type: application/csv-tab-delimited-table");
header("Content-disposition: filename=nom_fichier.csv");
readfile("/tmp/nom_fichier.csv");
unlink("/tmp/nom_fichier.csv");

il n'est pas nécessaire de passer par un fichier.

Code:

$this->_helper->viewRenderer->setNoRender(true);
$this->_helper->layout->disableLayout();

header("Content-Type: application/csv-tab-delimited-table");
header("Content-disposition: filename=nom_fichier.csv");
//on récupère les données à insérer puis formatage pour le csv
//....

print(utf8_decode($data));

j'insiste n'utilise pas header mais $this->getResponse()->setHeader(...)
enfin pour garantir que cela fonctionne avec tout type de client pas seulement FF
je te conseille l'ensemble des headers que j'ai donné plus haut

A+JYT

Hors ligne

 

#14 07-04-2010 14:15:37

lefafa
Membre
Date d'inscription: 03-03-2010
Messages: 13

Re: [Résolu] Exporter des données en fichier CSV

@ sekaijin
merci pour tous ces conseils
j'ai donc créé une aide d'action en utilisant tes headers avec :
$this->getActionController()->getResponse()->setHeader

ainsi je peux utiliser n'importe où dans mon appli l'export CSV.

Hors ligne

 

#15 12-05-2011 09:48:18

jcb
Membre
Date d'inscription: 21-09-2010
Messages: 18

Re: [Résolu] Exporter des données en fichier CSV

sekaijin a écrit:

lefafa a écrit:

Encore merci à tous
grâce à vous j'ai enfin réussi à faire fonctionner mon export CSV

je vous donne le code :

Code:

$this->_helper->viewRenderer->setNoRender(true);
$this->_helper->layout->disableLayout();

//on récupère les données à insérer puis formatage pour le csv
//....

$fichier = fopen("/tmp/nom_fichier.csv", "w+");
fwrite($fichier, utf8_decode($data));
fclose($fichier);
        
header("Content-Type: application/csv-tab-delimited-table");
header("Content-disposition: filename=nom_fichier.csv");
readfile("/tmp/nom_fichier.csv");
unlink("/tmp/nom_fichier.csv");

il n'est pas nécessaire de passer par un fichier.

Code:

$this->_helper->viewRenderer->setNoRender(true);
$this->_helper->layout->disableLayout();

header("Content-Type: application/csv-tab-delimited-table");
header("Content-disposition: filename=nom_fichier.csv");
//on récupère les données à insérer puis formatage pour le csv
//....

print(utf8_decode($data));

j'insiste n'utilise pas header mais $this->getResponse()->setHeader(...)
enfin pour garantir que cela fonctionne avec tout type de client pas seulement FF
je te conseille l'ensemble des headers que j'ai donné plus haut

A+JYT

Ces header ne sont pas suffisants sous ie quand le site est en https. Malheureusement, je ne trouve pas quels header pour les fichiers csv, alors que j'ai trouvé pour PDF

Hors ligne

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages