通过HTTP提供非常大的二进制文件时内存不足

时间:2017-05-01 16:33:06

标签: perl file http out-of-memory cgi

下面的代码是我们正在使用的Perl CGI脚本的原始代码。即使对于非常大的文件,它似乎也可以工作,但不适用于非常大的文件。

目前的代码是:

return pt[n-1];

如果我正确理解了代码,它会在“打印”它之前将整个文件加载到内存中。当然我觉得加载和显示它会更好吗?但在阅读了许多论坛和教程之后,我仍然不确定如何使用标准的Perl库做到最好......

最后一个问题,为什么最后指定了“binmode”?

非常感谢任何提示或建议,

2 个答案:

答案 0 :(得分:5)

我不知道binmode $DLFILE的用途。 $DLFILE与文件句柄DLFILE无关,现在已经读取到文件的binmode已经有点迟了。这可能只是一个错误

您可以改用它。它使用现代Perl最佳实践,并以8K块的形式读取和发送文件

文件名似乎来自$ID,因此我不确定$name是否正确,但我无法告诉

确保保留大括号,因为该块使Perl恢复$/的旧值并关闭打开的文件句柄

my $files_location = "$c->{target_dir}/$ID";

{
    print "Content-Type: application/x-download\n";
    print "Content-Disposition: attachment; filename=$name\n\n";

    open my $fh, '<:raw', $files_location or Error('open', "file $files_location");
    local $/ = \( 8 * 1024 );

    print while <$fh>;
}

答案 1 :(得分:3)

您将整个文件立即拉入内存。最好逐行循环遍历文件,这可以消除这个问题。

另请注意,我已修改代码以使用正确的3-arg open,并使用词汇文件句柄而不是全局裸字句柄。

open my $fh, '<', $files_location or die $!;

print "Content-Type:application/x-download\n";
print "Content-Disposition:attachment;filename=$name\n\n";

while (my $line = <$fh>){
    print $line;
}

binmode来电在您此处显示的内容中似乎毫无用处,因为$DLFILE似乎不是有效的正在使用的变量(添加脚本顶部的use strict;use warnings; ...)