Page 1 sur 1

Forcer téléchargement d'un gros contenu en "streaming&q

Posté : 17 nov. 2008, 17:01
par cf357
Bonjour,

Je ne sais pas si ma question est réellement avancée ou non, je vous laisse seuls juges...

Voilà mon utilisateur peut exporter les résultats de sa dernière requete sous forme de fichier CSV.
Pour cela, j'exécute la requete associée, et je construit tout le contenu CSV au sein d'une variable,
puis je force le téléchargement de ce contenu via les headers.

Seulement voilà, lorsque cette variable dépasse une certaine taille, on atterit sur une page blanche. J'imagine que c'est le strlen() ou le md5() qui posent quelques soucis sur une variable de ce genre.

Quels sont les pistes que vous me conseillerez ? Y a-t-il un moyen de faire télécharger ce contenu en "flux" ?

Posté : 17 nov. 2008, 19:01
par Hywan
Hey :),

À quelle taille arrives-tu ?

Posté : 18 nov. 2008, 10:38
par cf357
Je dirais une vingtaine de Mo ...

Posté : 18 nov. 2008, 19:31
par Hywan
Et si tu ouvres un tampon, que tu écris au pas à pas dedans, et que tu envoies le tampon à la fin, ça te donne quoi ? Ce serait plus intelligent et moins coûteux en mémoire je pense.

Voir la gestion des tampons dans PHP.

Posté : 19 nov. 2008, 17:08
par cf357
L'idée est bonne, j'avais déjà testé (donc c'est forcément bon !!), mais le comportement n'est toujours pas le bon...

Au lieu d'obtenir une page blanche après 3 secondes, le serveur travaille pendant une petite minute, puis m'affiche la page blanche...

:x

Posté : 19 nov. 2008, 19:17
par Hywan
C'est possible de voir du code ou pas ?

Posté : 20 nov. 2008, 16:55
par cf357
Oui bien sûr...

        ob_start();
        $content = "";
        foreach ($users as $user)
        {
                $content .= $user;
                $content .= PHP_EOL;
        }

        define('CFG_SEND_FILENAME', 'export-users.txt');
        define('CFG_FILESIZE',      strlen($content));
        define('CFG_FILE_MD5',      md5($content));
        define('CFG_DATE_FORMAT',   'D, d M Y H:i:s');

        error_reporting(0);
        ini_set('zlib.output_compression', 0);

        header('Pragma: public');
        header('Last-Modified: '.gmdate(CFG_DATE_FORMAT).' GMT');
        header('Cache-Control: must-revalidate, pre-check=0, post-check=0, max-age=0');
        header('Content-Tranfer-Encoding: none');
        header('Content-Length: '.CFG_FILESIZE);
        header('Content-MD5: '.base64_encode(CFG_FILE_MD5));
        header('Content-type: plain/text');
        header('Content-Disposition: attachment; filename="'.CFG_SEND_FILENAME.'"');
        header('Date: '.gmdate(CFG_DATE_FORMAT, time()).' GMT');
        header('Expires: '.gmdate(CFG_DATE_FORMAT, time()+1).' GMT');
        header('Last-Modified: '.gmdate(CFG_DATE_FORMAT, time()).' GMT');

        echo $content;
        ob_end_flush();

Posté : 20 nov. 2008, 17:00
par Hywan
Et si tu fais quelque chose du genre (qui correspondrait plus à ma première idée) :
error_reporting(0); 
        ob_start();

        ini_set('zlib.output_compression', 0); 

        define('CFG_SEND_FILENAME', 'export-users.txt'); 
        define('CFG_FILESIZE',      strlen($content)); 
        define('CFG_FILE_MD5',      md5($content)); 
        define('CFG_DATE_FORMAT',   'D, d M Y H:i:s'); 

        header('Pragma: public'); 
        header('Last-Modified: '.gmdate(CFG_DATE_FORMAT).' GMT'); 
        header('Cache-Control: must-revalidate, pre-check=0, post-check=0, max-age=0'); 
        header('Content-Tranfer-Encoding: none'); 
        header('Content-Length: '.CFG_FILESIZE); 
        header('Content-MD5: '.base64_encode(CFG_FILE_MD5)); 
        header('Content-type: plain/text'); 
        header('Content-Disposition: attachment; filename="'.CFG_SEND_FILENAME.'"'); 
        header('Date: '.gmdate(CFG_DATE_FORMAT, time()).' GMT'); 
        header('Expires: '.gmdate(CFG_DATE_FORMAT, time()+1).' GMT'); 
        header('Last-Modified: '.gmdate(CFG_DATE_FORMAT, time()).' GMT'); 

        foreach ($users as $user)
                echo $user . PHP_EOL;
 
        ob_end_flush();

Posté : 21 nov. 2008, 18:19
par cf357
Une page blanche, pure, vierge de tout code, propre, lavée avec mir laine spécial buffer. :(

Posté : 23 nov. 2008, 21:42
par Hywan
Et si tu envoies autre chose sur la sortie ? Si tu n'envoies pas une en-tête de téléchargement ?
D'ailleurs, essaye des autres en-têtes, car utiliser un fichier (vide) et écrire un autre contenu me paraît étrange :?.

Posté : 28 nov. 2008, 12:30
par cf357
Bon en choissant d'afficher mes resultats 1000 par 1000, ça passe, mais par contre, ça met bien un temps relativement important pour retourner plusieurs dizaines de milliers d'utilisateurs....

Je retourne donc au titre du topic, quelqu'un connait-il les entetes qui vont bien pour un transfert de données sous forme de flux ?