WWW::CURL::Multi 模块出现写入错误

发布于 2024-10-13 03:50:48 字数 2170 浏览 4 评论 0原文

我正在尝试与 Perl 的 WWW::Curl::Multi 模块并行下载网络上的一堆文件,但收到以下错误:

  • Use of uninitialized value in ref-to-glob 位于 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;

I'm trying to download a bunch of files on the web in parallel with the Perl's WWW::Curl::Multi module but I'm receiving the following errors:

  • Use of uninitialized value in
    ref-to-glob cast at AA.pm line 17.

  • syswrite() on unopened filehandle at
    AA.pm line 17.

  • Use of uninitialized value in
    subroutine entry at AA.pm line 60.

I'll appreciate if someone can figure out why those errors come from.

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浅暮の光 2024-10-20 03:50:48

我看到您初始化了一个文件句柄 $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 中添加一行来打印该函数的输入 (@_),您会看到什么?

I see you initialize a filehandle $fh to store the downloaded data, but I don't see how that value ever gets passed to your tofile function. Do you need to say

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

instead of

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

?

What do you see if you put an extra line in tofile that prints out the inputs (@_) to that function?

美煞众生 2024-10-20 03:50:48

我意识到问题不在于脚本,而在于我使用的旧 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 的值。您可以通过在 for 循环中本地定义 $fh 并将其放入哈希中来修复。退出子程序时关闭
fh 在哈希中。

I've realized that the problem was not about the script, it was rather about the old BSD machine(with the old version of perl) I was using.

You can test the code with the following 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);

But there is another bug in that script after being able to run it, it outputs the contents to only the last file. Because we are changing the values of $fh. You can fix by defining $fh locally in the for loop and put it in a hash. When exiting the subroutine close the
fh's in the hash.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文