2011-01-20 3 views
0

Я пытаюсь загрузить кучу файлов в Интернете параллельно с модулем WWW :: Curl :: Multi Perl, но я получаю следующие ошибки:WWW :: CURL :: Multi модуль дает ошибку записи

  • Использование неинициализированного значения в реф-к-Глоб литых на AA.pm линии 17.

  • syswrite() на неоткрытой дескриптором в AA.pm линии 17.

  • использования неинициализированного значения в
    запись подпрограммы на AA.pm линии 60.

Я признателен, если кто-то может понять, почему эти ошибки происходят из.

package AA; 

use strict; 
use warnings; 
use WWW::Curl::Easy; 
use WWW::Curl::Multi; 
use Data::Dumper; 

sub new { 
my $class = shift; 
my $self = {}; 
bless $self, $class; 
return $self; 
} 

sub tofile { 
return syswrite($_[1], $_[0]); #This is where first and the second error occurs 
} 

sub downloadfiles{ 
my $self = shift; 
my $files = shift; 
my %easy; 
my $curl = WWW::Curl::Easy->new; 
my $active_handles = 0; 
my $curlm = WWW::Curl::Multi->new; 
my $dir = "dl/"; 
my $fh; 
foreach my $file (@$files) { 
    my $curl_id = $active_handles + 1; # This should be a handle unique id. 
    my $code = 0; 
    $easy{$curl_id} = $curl; 
    $code+= $curl->setopt(CURLOPT_PRIVATE, $curl_id); 

    #Open the filehandle 
    open($fh, ">$dir$curl_id") or die "\nopen: $!\n\n"; 
    binmode $fh; 

    # do the usual configuration on the handle 
    $code+= $curl->setopt(CURLOPT_FILE, *$fh); 
    $code+= $curl->setopt(CURLOPT_FAILONERROR, 1); 
    $code+= $curl->setopt(CURLOPT_HEADER, 1); 
    $code+= $curl->setopt(CURLOPT_CONNECTTIMEOUT, 2); 
    $code+= $curl->setopt(CURLOPT_URL, $file); 
    $code+= $curl->setopt(CURLOPT_WRITEFUNCTION, \&tofile); 
    $code+= $curl->setopt(CURLOPT_NOPROGRESS, 1); 
    $code+= $curl->setopt(CURLOPT_VERBOSE, 0); 
    $code+= $curl->setopt(CURLOPT_HEADER, 0); 

    if ($code ne 0) { 
    die("Failed to initialize curl"); 
    } 

    # Add some easy handles 
    $curlm->add_handle($curl); 
    $active_handles++; 
} 
print "\nActive handles: ".$active_handles."\n"; 
while ($active_handles) { 
    my $active_transfers = $curlm->perform; #This is where second error comes from 
    if ($active_transfers != $active_handles) { 
    while (my ($id, $return_value) = $curlm->info_read) { 
    print $id; 
    if ($id) { 
    $active_handles--; 
    my $actual_easy_handle = $easy{$id}; 
    delete $easy{$id}; 
    } 
    } 
    } 
} 
close $fh; 
} 

1; 

ответ

0

Я понял, что проблема не в скрипте, а скорее в старой машине BSD (со старой версией Perl), которую я использовал.

Вы можете проверить код следующие строки:

my @rrds=qw(http://www.google.com http://www.stackoverflow.com http://www.reddit.com); 
print Dumper(@rrds); 
my $fDl = AA->new; 
$fDl->downloadfiles(\@rrds); 

Но есть еще одна ошибка в том, что сценарий после того, как в состоянии запустить его, он выводит содержимое только последнего файла. Потому что мы меняем значения $ fh. Вы можете исправить, указав $ fh локально в цикле for и помещая его в хеш. Когда выходите из подпрограммы, закройте в хеш fh.

+0

btw в тюрьме freebsd, вероятно, вы продолжите получать ошибки из-за ограниченного доступа к системным вызовам. – systemsfault

1

Я вижу, вы инициализировать дескриптор $fh для хранения загруженных данных, но я не вижу, как это значение никогда не переходит в руки вашей tofile функции. Нужно ли вам сказать

$code+= $curl->setopt(CURLOPT_FILE, $fh); # or 
$code+= $curl->setopt(CURLOPT_FILE, *$fh); 

вместо

$code+= $curl->setopt(CURLOPT_FILE, *TBZ2); # whatever TBZ2 is 

?

Что вы видите, если вы добавили дополнительную строку в tofile, которая распечатывает входы (@_) этой функции?

+0

благодарит моб, пытаясь изменить имена переменных и удалить некоторые другие коды, чтобы упростить и опубликовать код в stackoverflow. Я забыл переименовать TBZ2 в $ fh. В реальном коде эта строка была правильной. Проблема не в коде. – systemsfault

Смежные вопросы