perl过载文件名下载

时间:2014-07-10 09:39:24

标签: perl download overloading filenames

我需要能够建议要下载的文件,但我必须在我的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 )

你会如何改变它?你会怎么做? 在此先感谢您的帮助

3 个答案:

答案 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{(.*)([^/]*)$};

这有三个简单的解决方案

1。边界条件

如上所述,您可以添加限制.*可以匹配的边界条件:

$file =~ m{(?:(.*)/)?([^/]*)$};
my $dir = $1 // '';
my $filename = $2;

或者这个有点复杂的lookbehind断言也可以强制执行边界:

$file =~ m{(.*)(?<![^/])([^/]*)$};
my $dir = $1;
my $filename = $2;

2。非贪心匹配

但是,最简单的正则表达式解决方案是使用非贪婪匹配.*?

$file =~ m{(.*?)([^/]*)$};
my ($dir, $filename) = ($1, $2);

基本上,只要您将.*置于任何地方,请检查您的假设。大多数情况下,您实际上需要.*?

3。用于解析文件路径的模块

奖励选项只是使用像File::Spec解析文件路径信息

这样的模块
use File::Spec;

my ($vol, $dirs, $filename) = File::Spec->splitpath( $file );