Документация
AnyEvent::HTTP
содержит код, который использует возможность HTTP 1.1 для возобновления загрузки.Я никогда не использовал его, поэтому не могу комментировать его пригодность.
Видимо, пример ожидает, что вы уже знаете, как использовать AnyEvent
, что, конечно, я сделалне знаю.Вам нужно изменить код, чтобы цикл событий, который он ожидал, уже был готов:
#!/usr/bin/perl
use strict;
use warnings;
use AnyEvent::HTTP;
my $url = "http://localhost/foo.txt";
my $file = "foo.txt";
sub download {
my ($url, $file, $cb) = @_;
open my $fh, "+>>:raw", $file
or die "could not open $file: $!";
my %hdr;
my $ofs = 0;
if (stat $fh and $ofs = -s _) {
$hdr{"if-unmodified-since"} = AnyEvent::HTTP::format_date((stat _)[9]);
$hdr{"range"} = "bytes=$ofs-";
}
http_get $url, (
headers => \%hdr,
on_header => sub {
my ($hdr) = @_;
if ($hdr->{Status} == 200 && $ofs) {
# resume failed
truncate $fh, $ofs = 0;
}
sysseek $fh, $ofs, 0;
return 1;
},
on_body => sub {
my ($data, $hdr) = @_;
if ($hdr->{Status} =~ /^2/) {
length $data == syswrite $fh, $data
or return; # abort on write errors
}
return 1;
},
sub {
my (undef, $hdr) = @_;
my $status = $hdr->{Status};
if (my $time = AnyEvent::HTTP::parse_date $hdr->{"last-modified"}) {
utime $fh, $time, $time;
}
if ($status == 200 || $status == 206 || $status == 416) {
# download ok || resume ok || file already fully downloaded
$cb->(1, $hdr);
} elsif ($status == 412) {
# file has changed while resuming, delete and retry
unlink $file;
$cb->(0, $hdr);
} elsif ($status == 500 or $status == 503 or $status =~ /^59/) {
# retry later
$cb->(0, $hdr);
} else {
$cb->(undef, $hdr);
}
}
);
}
my $quit = AnyEvent->condvar; #create a handle to exit the loop
download $url, $file, sub {
if ($_[0]) {
print "OK!\n";
} elsif (defined $_[0]) {
print "please retry later\n";
} else {
print "ERROR\n";
}
$quit->send; #quit the loop
};
$quit->recv; #start the loop
Ключом к его работе является условная переменная $quit
:
my $quit = AnyEvent->condvar; #handle to exit the loop
.
.
.
$quit->recv;
Это устанавливает цикл событий.Без цикла событий программа завершает работу до того, как вызов http_get
получит возможность что-либо сделать, кроме создания файла.Чтобы выйти из цикла обработки событий, мы вызываем $quit->send
в обратном вызове функции download
.