使用 Perl CGI 脚本上传文件不起作用

File upload using a Perl CGI script not working

以下代码没有任何语法错误,但仍然没有 working.Can 我为 $Domain 使用服务器 ip(如 100.100.100.100),并且应该为 $directory(i是指添加服务器IP还是域名?请帮忙

#!/usr/bin/perl
use CGI;
$CGI::POST_MAX= 100 * 1024;
$CGI::DISABLE_UPLOADS=0;
$Referer = $ENV{HTTP_REFERER};
$Domain = "xxx.com";
$cgi = new CGI;
$file=$cgi->upload('text');
print $cgi->header,
$cgi->start_html
(
        -title=>'CGI.pm File Upload'
);
print <<EOF;
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="text" size=60><br>
<input type="submit" value="Upload">
</form>
EOF
if($file)
{
        if($Referer =~ "$Domain")
        {
                $directory="var/www/cgi-bin/uploads";
                open UPLOAD, ">$directory$file";
                binmode UPLOAD;
                while(<$file>) {print UPLOAD;}
                close UPLOAD;
        }
}
$cgi->end_html;
exit;

看来您需要再读一遍 the documentation on file upload basics。他们的示例代码是:

use autodie;

# undef may be returned if it's not a valid file handle
if ( my $io_handle = $q->upload('field_name') ) {
    open ( my $out_file,'>>','/usr/local/web/users/feedback' );
    while ( my $bytesread = $io_handle->read($buffer,1024) ) {
        print $out_file $buffer;
    }
}

您的代码在风格上存在一些差异,但需要注意的重要一点是,当您的代码运行此行时:

$file=$cgi->upload('text');

然后 $file 包含一个打开的文件句柄。它不包含文件名。这意味着您的代码的这些行中至少存在三个错误:

$directory="var/www/cgi-bin/uploads";
open UPLOAD, ">$directory$file";
  1. 您存储在 $directory 中的值几乎肯定会以 / 开头(所以它是 /var/www/cgi-bin/uploads)。
  2. 您还需要在 $directory$file 之间添加另一个 /(否则,它将包含类似 /var/www/cgi-bin/uploadsmyfile.dat 的内容)。
  3. 您需要调用 $cgi->param('text') 来获取正在上传的文件的名称。

这就是阻止您的程序运行的原因。您的代码的上传部分应如下所示:

my $filename = $cgi->param('text');
my $fh       = $cgi->upload('text');

my $directory = '/var/www/cgi-bin/uploads';

open my $upload_fh, '>', "$directory/$filename"
  or die "Can't open '$directory/$filename': $!";

print $upload_fh $_ while <$fh>;

请注意,我在此处进行了一些风格上的改进:

  1. 使用了 open()
  2. 的 3 参数版本
  3. 使用词法文件句柄
  4. 检查 open() 调用是否成功,如果失败则终止程序并显示一条有用的错误消息

总而言之,您似乎是从已经过时大约二十年的资源中学习 CGI 编程的。您的代码看起来像是来自 1990 年代。

其他一些提示:

  1. 总是 use strictuse warnings
  2. 间接对象表示法 (new CGI) 可能非常混乱。请改用 CGI->new
  3. 我们知道 CGI.pm 中的 HTML 生成函数自上个千年末以来就是一个糟糕的想法。请不要使用它们。 Perl 有许多优秀的模板解决方案。
  4. 在 2017 年编写 CGI 程序是一个糟糕的想法。查看 CGI::Alternatives 了解现代 Perl Web 开发工具的介绍。