我需要能够建议要下载的文件,但我必须在我的CGI中读取和打印文件。我试着去找:
#!/usr/bin/perl -w
use strict;
push( @INC, $lib_directory );
require 'lib_utils.pl';
dl_file('/tmp/final.pdf');
作为主页(dl.pl)和
sub dl_file {
my ($file) = @_;
if ( ! -e $file) {
print "file does not exist";
return 0;
}
my $content = read_file( $file, binmode => ':utf8' ) ;
$file =~ m#(.*)([^/]*)$#;
my $directory = $1;
my $filename = $2;
chdir $directory;
my $form = new CGI;
print $form->header(
-type => 'application/octet-stream',
-attachment => $filename,
-filename => $filename,
-Content-Disposition => "attachment; filename=$filename",
);
$form->print($content);
return 1;
}
用于被调用的函数。有趣的是,这个代码工作得很好,如果我不去一个sub并拥有dl.pl中的所有代码但是只要我在子代码中移动代码,下载的文件就会在脚本之后调用(即dl.pl )
你会如何改变它?你会怎么做? 在此先感谢您的帮助
答案 0 :(得分:2)
你的行
$file =~ m#(.*)([^/]*)$#
将$1
包含整个$file
和$2
为空。你需要在某处使用斜杠,可能就像这样
$file =~ m#(.*)/([^/]*)$#
使目录可选也是有意义的,如此
$file =~ m#(?:(.*)/)?([^/]*)$#
my $directory = $1;
你必须写
chdir $directory if $directory
答案 1 :(得分:0)
这就是你的绊倒:
$file =~ m#(.*)([^/]*)$#;
您似乎正在尝试拆分" /tmp/final.pdf"进入目录和文件。但是你没有 - 这种模式将你分裂成:
print "F:",$filename,"\n";
print "D:",$directory,"\n";
此输出:
F:
D:/tmp/final.pdf
这就是您遇到问题的原因 - 您没有文件名,因此默认使用脚本名称。
我建议您改为:
my ( $directory, $filename ) = ( $file =~ m,(.*/)([\.\w]+)$, );
这给出了:
F:final.pdf
D:/tmp/
答案 2 :(得分:0)
正如已经说过的那样,你会因为.*
的贪婪匹配而受到影响,这将会占用整个字符串:
$file =~ m{(.*)([^/]*)$};
这有三个简单的解决方案
如上所述,您可以添加限制.*
可以匹配的边界条件:
$file =~ m{(?:(.*)/)?([^/]*)$};
my $dir = $1 // '';
my $filename = $2;
或者这个有点复杂的lookbehind断言也可以强制执行边界:
$file =~ m{(.*)(?<![^/])([^/]*)$};
my $dir = $1;
my $filename = $2;
但是,最简单的正则表达式解决方案是使用非贪婪匹配.*?
:
$file =~ m{(.*?)([^/]*)$};
my ($dir, $filename) = ($1, $2);
基本上,只要您将.*
置于任何地方,请检查您的假设。大多数情况下,您实际上需要.*?
。
奖励选项只是使用像File::Spec
解析文件路径信息
use File::Spec;
my ($vol, $dirs, $filename) = File::Spec->splitpath( $file );