2009-08-28 75 views
5

我的網絡應用程序使用CGI :: Application在Apache mod_perl上運行。我想提供生成文件的下載。在過去(在我們使用mod_perl和CGI :: App之前),我只是將一個csv文件假脫機生成STDOUT。現在我正在拍攝一些細節 - 使用Spreadsheet :: WriteExcel創建一個Excel電子表格 - 我似乎無法從文件句柄中打印出來。如何使用mod_perl和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; 
} 

輸出只是一個空白的響應,警告也是空白的。

我用來將電子表格寫入文件句柄的方法與documentation差不多,所以我認爲這個問題是由於我的CGI :: App noobery。該文檔建議的文件句柄方法和mod_perl也證明了相當無果。

我想我應該提到我在Windows上運行,而且我目前的解決方法是創建一個文件併爲用戶提供一個鏈接。然而,這在清除目錄以及何時這樣做以及對生成文件的訪問進行驗證方面存在更多問題。

對此提出建議?嚴厲的批評?

回答

4

你不應該需要惹STDOUT; CGI-App應該爲你正確處理。在嘗試發送數據之前,您還可能需要關閉文件句柄。

雖然它看起來並沒有爲Excel數據設置適當的內容類型。對於除text/html以外的其他內容,您需要手動設置它。嘗試是這樣的:

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; 

}

您還可能有興趣在CGI::Application::Plugin::Stream

+0

是的我猜想關閉文件句柄強制它刷新變量,所以我可以返回它。另外,我不得不在頭文件中添加'-attachment =>'filename.xls'',否則Firefox無法找出如何處理文件。 我會研究CGI :: A :: P :: Stream,但我們所做的文件不應該大到足以影響。 謝謝! – wes 2009-08-28 22:07:16

3

您想關閉工作簿。同樣,關閉句柄:

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

而不用在內存中的整個電子表格,你要麼寫出來一個文件,並將其流呢完成後(使用CGI::Application::Plugin::Stream可以在此幫助,但之後仍需要清理它,但實際上每個Web應用程序都應該有一個可定期清理的臨時目錄),或者在創建時打印它(這意味着要創建FH STDIN相反,在mod_perl下可能會更棘手或者可能會更復雜不)。

然後記得在完成後關閉工作簿。