Вопрос по perl – Почему мой CGI-скрипт для загрузки изображений, написанный на Perl, не работает?

2
<code>#!/usr/bin/perl 
use CGI ':standard';
use CGI::Carp qw(fatalsToBrowser); 
my $files_location; 
my $ID; 
my @fileholder;
$files_location = "C:\Users\user\Documents\hello\icon.png";
open(DLFILE, "<$files_location") ; 
@fileholder = <DLFILE>; 
close (DLFILE) ; 
print "Content-Type:application/x-download\n"; 
print "Content-Disposition:attachment;filename=$ID\n\n";
print @fileholder;
</code>

Когда я запускаю этот скрипт, вместо того, чтобы возвращатьicon.png файл возвращаетdownload.pl (название скрипта приведено выше) сno content внутри него. В чем проблема?

Скрипт я использую в настоящее время.

<code>#!C:\Perl64\bin\perl.exe -w 
use CGI qw(:standard);
use File::Copy qw( copy );
use File::Spec::Functions qw( catfile );
use constant IMG_DIR => catfile(qw(     D:\  ));
serve_logo(IMG_DIR);
sub serve_logo {
    my ($dir) = @_;

                my $cgi = CGI->new;

                my $file = "icon.png";
                #print $file;

                defined ($file)         or die "Invalid image name in CGI request\n";
                send_file($cgi, $dir, $file);


                return;
                }
sub send_file
  {
    my ($cgi, $dir, $file) = @_;
    my $path = catfile($dir, $file);
    open my $fh, '<:raw', $path         or die "Cannot open '$path': $!";
    print $cgi->header(         -type => 'application/octet-stream',         -attachment => $file,     ); 
    binmode STDOUT, ':raw';
     copy $fh => \*STDOUT, 8_192;      
    close $fh         or die "Cannot close '$path': $!";
    return;

} 
</code>

Ваш Ответ

2   ответа
7

@fileholder = <DLFILE>; чтобы хлебать двоичный файл. В Windows автоматическое преобразование концов строк приведет к хаосу в содержимом этого файла.

Другие проблемы:

Вы не проверяете возвращаемое значениеopen. Мы даже не знаем,open успешно.

Вы никогда не назначаете значение$ID, то есть вы отправляете"filename=\n\n" в твоем ответе.

Вы копируете двоичный файл, делая объем памяти вашей программы пропорциональным размеру двоичного файла. Надежные программы этого не делают.

Выuseing CGI.pm, но вы не используете его и не читали документы.

Вы используете файловый дескриптор голого слова (т.е. глобальный пакет).

Фундаментальная причина заключается в том, чтоopen не удается. Почемуopen провал? Просто

C:\temp> cat uu.pl
#!/usr/bin/env perl

use strict; use warnings;

my $files_location = "C:\Users\user\Documents\hello\icon.png";
print "$files_location\n";

Давай попробуем это сделать?

C:\temp> uu
Unrecognized escape \D passed through at C:\temp\uu.pl line 5.
Unrecognized escape \h passed through at C:\temp\uu.pl line 5.
Unrecognized escape \i passed through at C:\temp\uu.pl line 5.
C:SERSSERDOCUMENTSHELLOICON.PNG

Вот короткий сценарий, иллюстрирующий лучший способ:

use CGI qw(:standard);
use File::Copy qw( copy );
use File::Spec::Functions qw( catfile );

use constant IMG_DIR => catfile(qw(
    E:\ srv localhost images
));

serve_logo(IMG_DIR);

sub serve_logo {
    my ($dir) = @_;

    my %mapping = (
        'big' => 'logo-1600x1200px.png',
        'medium' => 'logo-800x600.png',
        'small' => 'logo-400x300.png',
        'thumb' => 'logo-200x150.jpg',
        'icon' => 'logo-32x32.gif',
    );

    my $cgi = CGI->new;

    my $file = $mapping{ $cgi->param('which') };
    defined ($file)
        or die "Invalid image name in CGI request\n";

    send_file($cgi, $dir, $file);

    return;
}

sub send_file {
    my ($cgi, $dir, $file) = @_;

    my $path = catfile($dir, $file);

    open my $fh, '<:raw', $path
        or die "Cannot open '$path': $!";

    print $cgi->header(
        -type => 'application/octet-stream',
        -attachment => $file,
    );

    binmode STDOUT, ':raw';

    copy $fh => \*STDOUT, 8_192;

    close $fh
        or die "Cannot close '$path': $!";

    return;
}

Я также разместил подробное объяснение в моем блоге.

+ 1 :: Хороший ответ. Ωmega
Ну, для некоторого определения работы вы можете быть правы. Но это не мое определениеза работо и ясно, что это не работает, иначе вы бы не разместили этот вопрос, верно? Я что-то здесь упускаю? Эта статья и содержащиеся в ней советы - дерьмо. Sinan Ünür
Похоже, текстовый файл копируется, а двоичный - нет. Есть ошибки. Знаете ли вы в любом случае о преодолении этой проблемы, чтобы я мог загружать все типы файлов. user1092042
Sitepoint.com / файлы загрузка-скрипты на Perl откуда я взял источник. Кажется, он работает нормально для него. Так, как я мог бы загрузить этот двоичный файл надежным способом. Любые учебники. user1092042
Даже в приведенной выше программе, когда я пытаюсь открыть файл .png, он печатает содержимое в окнах моего браузера. Даже если я копирую, вставляю это содержимое в файл и переименовываю в .png, он говорит, что файл недействителен. Почему это происходит user1092042
0

чтобы понять, что не так, поэтому для тех, кто оказался здесь (как и я), возникают случайные проблемы с обслуживанием больших файлов, вот мой совет:

Avoid File :: Copy, поскольку он прослушивается для этой цели. При обработке данных через CGI syswrite может возвращать undef ($! - «Ресурс временно недоступен») в течение некоторого времени.

File :: Копирование останавливается в этом случае (возвращает 0, устанавливает $!), При этом не удается передать весь файл (или поток).

Множество разных вариантов, чтобы обойти это, повторить syswrite или использовать блокирующие сокеты, но не уверен, какой из них лучший!

Похожие вопросы