Как мне выполнить загрузку с кодированной передачей с помощью WWW:Mechanize?
Я пытаюсь использовать определенный веб-сервис и могу успешно выполнить загрузку с помощью следующей команды:
curl -X POST --header "Transfer-Encoding: chunked" -d @Downloads/file.pdf https://some.webservice/upload
Я получаю ответ JSON, указывающий на успех.
Однако я не могу понять, как сделать то же самое с WWW::Mechanize.
$mech->post("https://" . $server . "/upload", Content_Type => 'multipart/form-data', Content => [upID => $upid, name => $dlfile, userID => 0, userK => 0, file_0 => [$dlfile]]);
Он получает аналогичный ответ json с большим жирным сообщением об ошибке.
Нужно ли сначала явно устанавливать заголовок Transfer-Encoding? Есть ли какая-то другая хитрость? Google не проливает много света на это, Perlmonks тоже, а документация немного тупая.
2 ответа
Вы можете сделать это используя HTTP::Request::StreamingUpload
my $starttime = time();
my $req = HTTP::Request::StreamingUpload->new(
POST => $url,
path => $file,
headers => HTTP::Headers->new(
'Transfer-Encoding' => 'chunked'
),
);
my $gen = $req->content;
die unless ref($gen) eq "CODE";
my $total = 0;
$req->content(sub {
my $chunk = &$gen();
$total += length($chunk);
print "\r$total / $size bytes ("
. int($total/$size*100)
. "%) sent, "
. int($total/1000/(time()-$starttime+1))
. " k / sec ";
return $chunk;
});
my $resp = $ua->request($req);
print "\n";
unless ($resp->is_success) {
die "Failed uploading the file: ", $resp->status_line;
}
my $con = $resp->content;
return $con;
Вы действительно нуждаетесь WWW::Mechanize
? Это подкласс LWP::UserAgent
с дополнительными функциями, которые предоставляют функции, аналогичные браузеру, такие как заполнение и отправка форм, переход по ссылкам, история страниц с операцией "назад" и т. д. Если вам все это не нужно, вы также можете использовать LWP::UserAgent
непосредственно
В любом случае, post
метод наследуется без изменений от LWP::UserAgent
и можно использовать его напрямую, как вы сделали
Способ отправить чанк POST
это установить Content
на ссылку на подпрограмму. Подпрограмма должна возвращать следующий фрагмент данных каждый раз, когда она вызывается, и, наконец, ann пустую строку или undef
когда больше нечего отправить
Должны ли данные быть строкой JSON?
Проще всего написать фабричную подпрограмму, которая возвращает замыкание, как это
sub make_callback {
my ($data) = shift;
sub { substr($data, 0, 512, "") }
}
Тогда вы можете позвонить post
как это
my $payload = to_json(...);
$mech->post(
"https://$server/upload",
Content_Type => 'multipart/form-data',
Content => make_callback($payload)
);
Пожалуйста, имейте в виду, что все это не проверено