AnyEvent-MultiDownload
view release on metacpan or search on metacpan
lib/AnyEvent/MultiDownload.pm view on Meta::CPAN
#!/usr/bin/perl
package AnyEvent::MultiDownload;
use strict;
use utf8;
use Moo;
use AE;
use Asset::File;
use AnyEvent::Digest;
use List::Util qw/shuffle/;
use AnyEvent::HTTP qw/http_get/;
our $VERSION = '1.13';
has path => (
is => 'ro',
isa => sub {
die "æä»¶åå¨" if -e $_[0];
},
required => 1,
);
has url => (
is => 'ro',
required => 1,
);
has mirror => (
is => 'rw',
predicate => 1,
isa => sub {
return 1 if ref $_[0] eq 'ARRAY';
},
);
has digest => (
is => 'rw',
isa => sub {
return 1 if $_[0] =~ /Digest::(SHA|MD5)/;
}
);
has on_finish => (
is => 'rw',
required => 1,
isa => sub {
return 2 if ref $_[0] eq 'CODE';
}
);
has on_error => (
is => 'rw',
isa => sub {
return 2 if ref $_[0] eq 'CODE';
},
default => sub { sub { 1 } },
);
has on_block_finish => (
is => 'rw',
isa => sub {
return 2 if ref $_[0] eq 'CODE';
},
lib/AnyEvent/MultiDownload.pm view on Meta::CPAN
sub retry {
my ($self, $task, $retry) = @_;
my $w;$w = AE::timer( $self->retry_interval, 0, sub {
$task->{pos} = $task->{ofs}; # é䏿¬åæ¶è¦ seek åé¶
$task->{size} = 0;
$task->{ctx} = undef;
$self->fetch_block( $task, ++$retry );
undef $w;
});
}
sub split_range {
my $self = shift;
my $length = shift;
# æ¯ä¸ªè¯·æ±ç段大å°çèå´,åè
my $block_size = $self->block_size;
my $segments = int($length / $block_size);
# è¦å¤ççåèçæ»æ°
my $len_remain = $length;
my @ranges;
my $block = 0;
while ( $len_remain > 0 ) {
# æ¯ä¸ª segment ç大å°
my $seg_len = $block_size;
# åç§»é¿åº¦
my $ofs = $length - $len_remain;
# å©ä½åè
$len_remain -= $seg_len;
my $tail = $ofs + $seg_len - 1;
if ( $length-1 < $tail) {
$tail = $length-1;
}
my $task = {
block => $block, # å½ååç¼å·
ofs => $ofs, # å½åçåç§»é
pos => $ofs, # æ¬åçèµ·ç¹
tail => $tail, # æ¬åçç»æ
range => 'bytes=' . $ofs . '-' . $tail,
size => 0, # æ»å
±ä¸è½½çé¿åº¦
};
$self->tasks->[$block] = $task;
$block++;
}
}
1;
__END__
=pod
=encoding utf8
=head1 NAME
AnyEvent::MultiDownload - éé»å¡çå¤çº¿ç¨å¤å°åæä»¶ä¸è½½ç模å
=head1 SYNOPSIS
è¿æ¯ä¸ä¸ªå
¨éé»å¡çå¤çº¿ç¨å¤å°åæä»¶ä¸è½½ç模å, å¯ä»¥è±¡ä¸é¢è¿ä¸ªåºç¨ä¸æ ·, åæ¶ä¸è½½å¤ä¸ªæä»¶, 并䏿´ä¸ªè¿ç¨é½æ¯å¼æ¥äºä»¶è§£å, ä¸ä¼é»å¡ä¸»è¿ç¨.
ä¸é¢æ¯ä¸ªç®åçä¾å, åæ¶ä»å¤ä¸ªå°åä¸è½½åä¸ä¸ªæä»¶.
use AE;
use AnyEvent::MultiDownload;
my @urls = (
'http://mirrors.163.com/centos/7/isos/x86_64/CentOS-7.0-1406-x86_64-DVD.iso',
'http://mirrors.sohu.com/centos/7/isos/x86_64/CentOS-7.0-1406-x86_64-DVD.iso',
);
my $cv = AE::cv;
my $MultiDown = AnyEvent::MultiDownload->new(
url => pop @urls,
mirror => \@urls,
path => '/tmp/ubuntu.iso',
block_size => 1 * 1024 * 1024, # 1M
on_block_finish => sub {
my ($hdr, $block_ref, $md5) = @_;
if ($md5 eq $src_md5) {
return 1;
}
0
},
on_finish => sub {
my $len = shift;
$cv->send;
},
on_error => sub {
my ($error, $hdr) = @_;
$cv->send;
}
)->start;
$cv->recv;
ä¸é¢æ¯å¼æ¥åæ¶ä¸è½½å¤ä¸ªæä»¶çå®ä¾. æ´ä¸ªè¿ç¨å¼æ¥.
use AE;
use AnyEvent::MultiDownload;
my $cv = AE::cv;
$cv->begin;
my $MultiDown = AnyEvent::MultiDownload->new(
url => 'http://xxx/file1',
path => "/tmp/file2",
on_finish => sub {
my $len = shift;
$cv->end;
},
( run in 0.901 second using v1.01-cache-2.11-cpan-39bf76dae61 )