WWW :: CURL :: Multi модуль дает ошибку записи - PullRequest
0 голосов
/ 20 января 2011

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

  • Использование неинициализированного значения в бросок ref-to-glob на линии AA.pm 17.

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

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

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

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;

Ответы [ 2 ]

1 голос
/ 20 января 2011

Я вижу, что вы инициализируете дескриптор файла $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 голосов
/ 20 января 2011

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

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

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 в хэше.

...