2009-08-28 8 views
5

Meine Web-App läuft auf Apache mod_perl mit CGI :: Application. Ich möchte einen Download einer generierten Datei bereitstellen. In der Vergangenheit (bevor wir mod_perl und CGI :: App verwendet haben) habe ich gerade eine csv-Datei an ausgegeben, wie sie generiert wurde. Jetzt mache ich ein wenig mehr Raffinesse - ich erstelle ein Excel-Spreadsheet mit Spreadsheet :: WriteExcel - und ich kann nicht scheinen, es aus dem Datei-Handle auszudrucken.Wie kann ich einen temporären Datei-Download mit mod_perl und CGI :: Application bereitstellen?

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; 
} 

Die Ausgabe ist nur eine leere Antwort, und die Warnung ist ebenfalls leer.

Die Methode, die ich benutze, um die Tabelle in ein Dateihandle zu schreiben, ist ziemlich direkt aus der documentation, also nehme ich an, dass das Problem aufgrund einiger CGI :: App noobery meinerseits ist. Die vorgeschlagenen Methoden der Dokumentation für Dateihandles und mod_perl erwiesen sich ebenfalls als ziemlich fruchtlos.

Ich denke, ich sollte erwähnen, dass ich unter Windows laufe, und dass meine aktuelle Problemumgehung darin besteht, eine Datei zu erstellen und dem Benutzer einen Link zu ihm bereitzustellen. Das wirft jedoch mehr Probleme auf, wenn es darum geht, das Verzeichnis zu löschen und wenn dies der Fall ist, und auch eine Authentifizierung für den Zugriff auf die erzeugten Dateien.

Vorschläge? Zischende Kritik?

Antwort

4

Sie sollten nicht mit STDOUT zu verwirren müssen; CGI-App sollte das für Sie unter der Haube richtig handhaben. Möglicherweise müssen Sie auch das Dateihandle schließen, bevor Sie versuchen, die Daten zu senden.

Es sieht so aus, als ob Sie keinen richtigen Inhaltstyp für die Excel-Daten festlegen. Für etwas anderes als text/html müssen Sie es manuell einstellen. Probieren Sie etwas wie folgt aus:

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; 

}

Sie auch in CGI::Application::Plugin::Stream

+0

Ja, ich denke, das Schließen des Dateihandles zwingt ihn, die Variable zu leeren, damit ich sie zurückgeben kann. Außerdem musste ich '-attachment => 'filename.xls' im Header hinzufügen oder Firefox konnte nicht herausfinden, was mit der Datei zu tun war. Ich werde in CGI :: A :: P :: Stream schauen, aber die Dateien, die wir machen, sollten nicht groß genug sein, um von Bedeutung zu sein. Danke! – wes

3

Sie möchten die Arbeitsmappe schließen. Auch schließen Sie die Dateikennung:

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. 
4

Stattdessen interessiert sein die ganze Tabelle im Speicher zu schaffen, sollten Sie entweder schreiben in eine Datei und sie es streamen wenn fertig (mit CGI::Application::Plugin::Stream hilft hier, aber Sie müssten es immer noch aufräumen, aber wirklich jede Web-Anwendung sollte ein temporäres Verzeichnis, das regelmäßig aufgeräumt wird) oder drucken Sie es wie Sie es erstellen (was bedeutet, dass die FH STDIN stattdessen könnte das unter mod_perl oder vielleicht auch kniffliger sein sei nicht).

Und dann vergessen Sie nicht, Ihre Arbeitsmappe zu schließen, wenn es fertig ist.