如何使用 WWW:Mechanize 进行分块 transfer-encoding 上传?
How do I do a chunked transfer-encoding upload with 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 header 吗?还有其他技巧吗? Google 对此没有太多说明,Perlmonks 也没有,而且文档有点迟钝。
你真的需要WWW::Mechanize
吗?它是 LWP::UserAgent
的子类,具有附加功能,可提供类似浏览器的功能,例如填写和提交表单、单击链接、具有 "back" 操作的页面历史记录等。如果您不需要全部那么你也可以直接使用LWP::UserAgent
无论哪种方式,post
方法都是继承自LWP::UserAgent
,原封不动的,直接用就好了
发送分块 POST
的方法是将 Content
设置为对子例程的引用。子例程每次调用时必须 return 下一个数据块,最后一个空字符串或 undef
当没有更多要发送时
数据应该是 JSON 字符串吗?
写一个 return 是一个闭包的工厂子例程是最简单的,就像这样
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)
);
请注意,所有这些都未经测试
您可以使用 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;
我正在尝试使用特定的网络服务,我可以使用以下命令成功执行上传:
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 header 吗?还有其他技巧吗? Google 对此没有太多说明,Perlmonks 也没有,而且文档有点迟钝。
你真的需要WWW::Mechanize
吗?它是 LWP::UserAgent
的子类,具有附加功能,可提供类似浏览器的功能,例如填写和提交表单、单击链接、具有 "back" 操作的页面历史记录等。如果您不需要全部那么你也可以直接使用LWP::UserAgent
无论哪种方式,post
方法都是继承自LWP::UserAgent
,原封不动的,直接用就好了
发送分块 POST
的方法是将 Content
设置为对子例程的引用。子例程每次调用时必须 return 下一个数据块,最后一个空字符串或 undef
当没有更多要发送时
数据应该是 JSON 字符串吗?
写一个 return 是一个闭包的工厂子例程是最简单的,就像这样
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)
);
请注意,所有这些都未经测试
您可以使用 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;