如何使用WWW进行分块传输编码上传:Mechanize?

时间:2017-03-02 21:06:03

标签: perl www-mechanize lwp chunked-encoding chunked

我正在尝试使用特定的Web服务,我可以使用以下命令成功执行上载:

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标头?还有其他一些技巧吗?谷歌对此没有太多了解,Perlmonks也没有,而且文档有点迟钝。

2 个答案:

答案 0 :(得分:4)

你真的需要WWW::Mechanize吗?它是LWP::UserAgent的子类,具有附加功能,提供类似浏览器的功能,如填写和提交表单,单击链接,带有“后退”操作的页面历史记录等。如果您不需要所有这些你也可以直接使用LWP::UserAgent

无论哪种方式,post方法都会从LWP::UserAgent继承,并且可以直接使用它

发送分块POST的方法是将Content设置为对子例程的引用。子程序每次调用时都必须返回下一个数据块,最后一个空字符串或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)
);

请注意,所有这些都是未经测试的

答案 1 :(得分:3)

您可以使用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;