通过 HTTP 提供非常大的二进制文件时内存不足
Out of memory when serving a very big binary file over HTTP
下面的代码是我们正在使用的Perl CGI 脚本的原始代码。即使对于非常大的文件,它似乎也能正常工作,但对于非常大的文件就不行了。
当前代码是:
$files_location = $c->{target_dir}.'/'.$ID;
open(DLFILE, "<$files_location") || Error('open', 'file');
@fileholder = <DLFILE>;
close (DLFILE) || Error ('close', 'file');
print "Content-Type:application/x-download\n";
print "Content-Disposition:attachment;filename=$name\n\n";
print @fileholder;
binmode $DLFILE;
如果我对代码的理解正确,它会在 "printing" 之前将整个文件加载到内存中。当然,我想按块加载和显示它会好得多吗?但是在阅读了许多论坛和教程之后,我仍然不确定如何使用标准的 Perl 库来做到最好...
最后一个问题,为什么最后指定"binmode"?
非常感谢任何提示或建议,
您一次将整个文件拉入内存。最好逐行遍历文件,这样就消除了这个问题。
另请注意,我修改了代码以使用正确的 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
似乎不是有效的正在使用的变量(添加 [=脚本顶部的 13=] 和 use warnings;
...)
我不知道 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>;
}
下面的代码是我们正在使用的Perl CGI 脚本的原始代码。即使对于非常大的文件,它似乎也能正常工作,但对于非常大的文件就不行了。
当前代码是:
$files_location = $c->{target_dir}.'/'.$ID;
open(DLFILE, "<$files_location") || Error('open', 'file');
@fileholder = <DLFILE>;
close (DLFILE) || Error ('close', 'file');
print "Content-Type:application/x-download\n";
print "Content-Disposition:attachment;filename=$name\n\n";
print @fileholder;
binmode $DLFILE;
如果我对代码的理解正确,它会在 "printing" 之前将整个文件加载到内存中。当然,我想按块加载和显示它会好得多吗?但是在阅读了许多论坛和教程之后,我仍然不确定如何使用标准的 Perl 库来做到最好...
最后一个问题,为什么最后指定"binmode"?
非常感谢任何提示或建议,
您一次将整个文件拉入内存。最好逐行遍历文件,这样就消除了这个问题。
另请注意,我修改了代码以使用正确的 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
似乎不是有效的正在使用的变量(添加 [=脚本顶部的 13=] 和 use warnings;
...)
我不知道 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>;
}