Comment puis-je fournir un téléchargement de fichier temporaire en utilisant mod_perl et CGI :: Application?

Mon application web s’exécute sur Apache mod_perl utilisant CGI :: Application. Je souhaite fournir un téléchargement d’un fichier généré. Dans le passé (avant que nous mod_perl et CGI :: App), je venais de spouler un fichier csv dans STDOUT fur et à mesure de sa génération. Maintenant, je cherche un peu plus de raffinement – créer une feuille de calcul Excel à l’aide de Spreadsheet :: WriteExcel – et je n’arrive pas à l’imprimer à partir du descripteur de fichier.

 sub export_list { my $self = shift; binmode(STDOUT); my $str; open my $fh, '>', \$str; my $workbook = Spreadsheet::WriteExcel->new($fh); my $worksheet = $workbook->add_worksheet(); $worksheet->write_col(0,0, ['some','data','here']); warn $str; return $str; } 

La sortie est juste une réponse vide, et l’avertissement est également vide.

La méthode que j’utilise pour écrire la feuille de calcul dans un descripteur de fichier est quasiment directement issue de la documentation , donc je suppose que le problème est dû à certains noeuds CGI :: App de ma part. Les méthodes suggérées par la documentation pour les descripteurs de fichiers et mod_perl avérées inutiles.

Je suppose que je devrais mentionner que je fonctionne sous Windows, et que ma solution actuelle consiste à créer un fichier et à fournir à l’utilisateur un lien vers celui-ci. Cela pose plus de problèmes, cependant, en ce qui concerne la suppression du répertoire et du moment, ainsi que l’authentification pour l’access aux fichiers générés.

Suggestions? Critique cinglante?

Vous ne devriez pas avoir besoin de jouer avec STDOUT ; CGI-App devrait gérer cela correctement pour vous sous le capot. Vous devrez peut-être également fermer le descripteur de fichier avant d’essayer d’envoyer les données.

Il semble que vous ne définissiez pas un type de contenu approprié pour les données Excel. Pour autre chose que text / html, vous devez le définir manuellement. Essayez quelque chose comme ça:

 sub export_list { my $self = shift; my $str; open my $fh, '>', \$str or die "Can't open to var: $!"; my $workbook = Spreadsheet::WriteExcel->new($fh); my $worksheet = $workbook->add_worksheet(); $worksheet->write_col(0,0, ['some','data','here']); $workbook->close; close $fh; warn $str; $self->header_add( -type => 'application/vnd.ms-excel' ); return $str; 

}

Vous pouvez également être intéressé par CGI :: Application :: Plugin :: Stream

Au lieu de créer l’intégralité de la feuille de calcul en mémoire, vous devez soit l’écrire dans un fichier et la diffuser une fois terminé (en utilisant CGI :: Application :: Plugin :: Stream aide ici, mais vous devrez toujours le nettoyer par la suite). , mais en réalité chaque application web doit avoir un répertoire temporaire qui est nettoyé périodiquement) ou l’imprimer au fur et à mesure de sa création (ce qui signifie que STDIN peut être plus compliqué sous mod_perl ou pas).

Et puis n’oubliez pas de fermer votre classeur lorsque c’est fait.

Vous souhaitez fermer le classeur. Fermez également le descripteur de fichier:

 warn "length 1=".length($str); $workbook->close(); close($fh) or die "error on close: $!"; warn "length 2=".length($str); length 1=0 at wx.pl line 16. length 2=5632 at wx.pl line 19.