2009-08-28 19 views
5

Ứng dụng web của tôi chạy trên Apache mod_perl bằng CGI :: Ứng dụng. Tôi muốn cung cấp tải xuống tệp được tạo. Trong quá khứ (trước khi chúng tôi đang sử dụng mod_perl và CGI :: App), tôi chỉ tạo một tệp csv thành STDOUT khi được tạo. Bây giờ tôi đang chụp cho một chút tinh tế hơn - tạo ra một bảng tính Excel bằng cách sử dụng bảng tính :: WriteExcel - và tôi không thể có vẻ nó để có được in nó ra từ xử lý tập tin.Làm cách nào để có thể tải xuống tệp tạm thời bằng cách sử dụng mod_perl và 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; 
} 

Đầu ra chỉ là một phản hồi trống và cảnh báo cũng trống.

Phương pháp tôi đang sử dụng để viết bảng tính thành tệp tập tin là khá thẳng ra khỏi số documentation, vì vậy tôi giả định vấn đề là do một số CGI :: Ứng dụng noobery về phía tôi. Các phương pháp được đề xuất của tài liệu hướng dẫn cho các tệp thủ công và mod_perl cũng tỏ ra khá vô nghĩa.

Tôi đoán tôi nên đề cập đến tôi đang chạy trên Windows và cách khắc phục hiện tại của tôi là tạo tệp và cung cấp cho người dùng liên kết đến nó. Điều đó đặt ra nhiều vấn đề hơn, tuy nhiên, liên quan đến thanh toán bù trừ ra khỏi thư mục và khi làm như vậy, và cũng xác thực để truy cập vào các tập tin được tạo ra.

Đề xuất? Tranh chấp gay gắt?

Trả lời

4

Bạn không cần phải gây rối với STDOUT; CGI-App nên xử lý đúng cách cho bạn dưới mui xe. Bạn cũng có thể cần phải đóng tập tin trước khi bạn cố gắng gửi dữ liệu.

Dường như bạn không đặt loại nội dung phù hợp cho dữ liệu Excel. Đối với bất kỳ thứ gì ngoài văn bản/html, bạn sẽ cần phải đặt thủ công. Hãy thử một cái gì đó như thế này:

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; 

}

Bạn cũng có thể quan tâm đến CGI::Application::Plugin::Stream

+0

Vâng, tôi đoán việc đóng filehandle buộc nó phải chuyển sang biến để tôi có thể trả lại. Ngoài ra, tôi đã phải thêm '-attachment => 'filename.xls'' vào tiêu đề hoặc firefox không thể tìm ra việc cần làm với tệp. Tôi sẽ xem xét CGI :: A :: P :: Stream, nhưng các tệp chúng tôi đang tạo ra không đủ lớn để quan trọng. Cảm ơn! – wes

3

Bạn muốn đóng sổ làm việc. Đồng thời đóng filehandle:

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

Thay vì tạo ra toàn bộ bảng tính trong bộ nhớ, bạn có nên viết nó ra vào một tập tin và chúng dòng nó khi hoàn thành (sử dụng CGI::Application::Plugin::Stream giúp ở đây, nhưng bạn vẫn cần phải dọn dẹp sau đó, nhưng thực sự mọi ứng dụng web nên có thư mục tạm thời được dọn dẹp định kỳ) hoặc in nó khi bạn tạo nó (có nghĩa là làm cho FH STDIN thay vào đó có thể phức tạp hơn dưới mod_perl hoặc có thể không được).

Và sau đó nhớ đóng sổ làm việc của bạn khi hoàn thành.