如何使用 mod_perl 和 CGI​​::Application 提供临时文件下载?

发布于 2024-08-02 19:27:27 字数 951 浏览 7 评论 0原文

我的 Web 应用程序使用 CGI::Application 在 Apache mod_perl 上运行。我想提供生成文件的下载。过去(在我们使用 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 上运行,并且我当前的解决方法是创建一个文件并向用户提供指向该文件的链接。然而,这在清除目录、何时清除以及访问生成文件的身份验证方面带来了更多问题。

建议?严厉批评?

My web app runs on Apache mod_perl using CGI::Application. I want to provide a download of a generated file. In the past (before we were using mod_perl and CGI::App) I just spooled out a csv file to STDOUT as it was generated. Now I'm shooting for a little more refinement - creating an Excel spreadsheet using Spreadsheet::WriteExcel - and I can't seem it to get to print it out from the file handle.

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

The output is just a blank response, and the warn is blank as well.

The method I'm using to write the spreadsheet to a filehandle is pretty much straight out of the documentation, so I assume the problem is due to some CGI::App noobery on my part. The documentation's suggested methods for filehandles and mod_perl proved pretty fruitless as well.

I guess I should mention I'm running on Windows, and that my current workaround is to create a file and provide the user with a link to it. That poses more problems, however, in regards to clearing out the directory and when to do so, and also authentication for access to the generated files.

Suggestions? Scathing criticism?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

成熟稳重的好男人 2024-08-09 19:27:27

您不需要搞乱 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

You shouldn't need to mess with STDOUT; CGI-App should handle that properly for you under the hood. You'll also may need to close the filehandle before you try to send the data.

It looks like you're not setting a proper content type for the Excel data, though. For anything other than text/html, you'll need to set it manually. Try something like this:

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;

}

You may also be interested in CGI::Application::Plugin::Stream

并安 2024-08-09 19:27:27

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

然后记住完成后关闭工作簿。

Instead of creating the whole spreadsheet in memory, you should either write it out to a file and them stream it when finished (using CGI::Application::Plugin::Stream helps here, but you'd still need to clean it up afterwards, but really every web app should have a temp directory that periodically gets cleaned up) or print it as you create it (which means making the FH STDIN instead which might be trickier under mod_perl or maybe not).

And then remember to close your workbook when it's done.

终遇你 2024-08-09 19:27:27

您想要关闭工作簿。同时关闭文件句柄:

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.

You want to close the workbook. Also close the 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.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文