我需要提供一个大文件(500 MB),以便从Web服务器无法访问的位置下载.我找到了问题
Serving large files with PHP,这与我的情况相同,但我使用的是Perl而不是PHP.
我尝试逐行打印文件,但这不会导致浏览器在抓取整个文件之前提示下载:
use Tie::File; open my $fh,'<','/path/to/file.txt'; tie my @file,'Tie::File',$fh or die 'Could not open file: $!'; my $size_in_bytes = -s $fh; print "Content-type: text/plain\n"; print "Content-Length: $size_in_bytes\n"; print "Content-Disposition: attachment; filename=file.txt\n\n"; for my $line (@file) { print $line; } untie @file; close $fh; exit;
解决方法
如果你只想将输入粘贴到输出,这应该可以解决问题.
use Carp (); { #Lexical For FileHandle and $/ open my $fh,'/path/to/file.txt' or Carp::croak("File Open Failed"); local $/ = undef; print scalar <$fh>; close $fh or Carp::carp("File Close Failed"); }
我想回应“Perl是否有PHP ReadFile Equivelant”,我想我的回答是“但它并不真的需要一个”.
我已经使用了PHP的手动文件IO控件,它们很痛苦,相比之下,Perls只是如此易于使用,因为一个适合所有人的功能似乎过度杀戮.
此外,您可能希望查看X-SendFile支持,并基本上向您的Web服务器发送一个标头,告诉它要发送什么文件:http://john.guen.in/past/2007/4/17/send_files_faster_with_xsendfile/(当然假设它有足够的权限来访问该文件,但该文件通常不正常可通过标准URI访问)
编辑注释,最好在循环中执行它,我用硬盘驱动器测试上面的代码,并且它隐式地尝试将整个事物存储在一个不可见的临时变量中并且吃掉你所有的ram.
替代使用块
以下改进的代码以8192个字符块的形式读取给定文件,这样可以提高内存效率,并且可以获得与我的磁盘原始读取速率相当的吞吐量. (我还指出它/ dev / full适合和咯咯笑,并且获得了500mb / s的健康吞吐量,它并没有吃掉我所有的公羊,所以一定很好)
{ open my $fh,'/dev/sda' ; local $/ = \8192; # this tells IO to use 8192 char chunks. print $_ while defined ( $_ = scalar <$fh> ); close $fh; }
应用jrockways建议
{ open my $fh,'/dev/sda5' ; print $_ while ( sysread $fh,$_,8192 ); close $fh; }
这实际上使性能提高了一倍……在某些情况下,我获得了比DD更好的吞吐量O_o.