2009-08-28 10 views
5

Moja aplikacja internetowa działa na serwerze Apache mod_perl przy użyciu aplikacji CGI :: Application. Chcę dostarczyć pobrany plik. W przeszłości (zanim korzystaliśmy z aplikacji mod_perl i CGI :: App) właśnie wygenerowałem plik CSV do STDOUT, ponieważ został wygenerowany. Teraz kręcę, by trochę bardziej wyrafinować - stworzyć arkusz kalkulacyjny Excela za pomocą arkusza kalkulacyjnego :: WriteExcel - i nie mogę tego wydrukować z uchwytu pliku.Jak mogę zapewnić pobranie pliku tymczasowego za pomocą mod_perl i CGI :: Application?

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

Dane wyjściowe to tylko pusta odpowiedź, a ostrzeżenie jest puste.

Metoda, której używam do zapisywania arkusza kalkulacyjnego do uchwytu pliku, jest prawie prosta z documentation, więc zakładam, że problem jest spowodowany przez niektóre noobery aplikacji CGI :: App z mojej strony. Sugerowane metody dokumentacji uchwytów plików i mod_perl okazały się również bezowocne.

Chyba powinienem wspomnieć, że używam systemu Windows i że moim obecnym obejściem jest utworzenie pliku i udostępnienie użytkownikowi łącza do niego. Stwarza to jednak więcej problemów w odniesieniu do czyszczenia katalogu i kiedy to zrobić, a także uwierzytelniania dostępu do wygenerowanych plików.

Sugestie? Zjadliwa krytyka?

Odpowiedz

4

Nie powinieneś zadzierać z STDOUT; CGI-App powinna obsługiwać to poprawnie dla Ciebie pod maską. Konieczne może być również zamknięcie uchwytu pliku przed próbą wysłania danych.

Wygląda jednak na to, że nie ustawiasz odpowiedniego typu zawartości dla danych Excel. W przypadku czegokolwiek innego niż tekst/HTML, musisz ustawić go ręcznie. Spróbuj czegoś takiego:

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; 

}

Możesz być także zainteresowany CGI::Application::Plugin::Stream

+0

Tak, domyślam się, że zamknięcie uchwytu pliku zmusza go do opróżnienia zmiennej, więc mogę ją zwrócić. Musiałem też dodać do nagłówka '-attachment => 'filename.xls'' lub firefox nie mógł się dowiedzieć, co zrobić z tym plikiem. Zajrzę do CGI :: A :: P :: Stream, ale pliki, które tworzymy, nie powinny być wystarczająco duże, aby mieć znaczenie. Dzięki! – wes

3

Chcesz zamknąć skoroszyt. Zamknij również uchwyt pliku:

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

Zamiast tworzyć cały arkusz w pamięci, należy albo zapisać go do pliku i je przesyłać je po skończeniu (pomoc przynosi CGI::Application::Plugin::Stream, ale nadal trzeba to wyczyścić, ale tak naprawdę każda aplikacja internetowa powinna mieć katalog tymczasowy, który będzie okresowo oczyszczany) lub wydrukować go podczas jego tworzenia (co oznacza, że ​​FH STDIN zamiast tego może być trudniejsze pod mod_perl lub może nie być).

A następnie pamiętaj, aby zamknąć skoroszyt, gdy jest to zrobione.

Powiązane problemy