5

mod_perl我的网络应用程序使用 CGI::Application在 Apache 上运行。我想提供生成文件的下载。过去(在我们使用mod_perl和 CGI​​::App 之前)我只是在生成 csv 文件时将STDOUT其输出。现在我要进行更多改进 - 使用 Spreadsheet::WriteExcel 创建一个 Excel 电子表格 - 我似乎无法从文件句柄中打印出来。

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

输出只是一个空白响应,警告也是空白。

我用来将电子表格写入文件句柄的方法几乎直接来自文档,所以我认为问题是由于我的一些 CGI::App noobery 造成的。该文档建议的文件句柄方法也mod_perl被证明是徒劳的。

我想我应该提到我在 Windows 上运行,并且我当前的解决方法是创建一个文件并为用户提供指向它的链接。然而,这带来了更多问题,涉及清除目录和何时清除,以及访问生成文件的身份验证。

建议?严厉批评?

4

3 回答 3

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感兴趣

于 2009-08-28T21:39:48.007 回答
4

与其在内存中创建整个电子表格,不如将其写入文件并在完成时将其流式传输(在这里使用CGI::Application::Plugin::Stream会有所帮助,但之后您仍然需要清理它,但实际上每个 Web 应用程序都应该有一个临时目录,该目录会定期清理)或在创建时打印它(这意味着STDIN在 mod_perl 下制作 FH 可能会更棘手,也可能不会)。

然后记得在完成后关闭您的工作簿。

于 2009-08-28T21:41:51.653 回答
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.
于 2009-08-28T21:38:39.617 回答