2017-03-02 11 views
3

私は、特定のWebサービスを使用しようとするんだ、と私は成功し、次のコマンドを使用してアップロードを行うことができます。私は、JSONレスポンスを取り戻すWWW:Mechanizeでチャンクされた転送エンコーディングをアップロードするにはどうしたらいいですか?

curl -X POST --header "Transfer-Encoding: chunked" -d @Downloads/file.pdf https://some.webservice/upload 

は成功を示しています。

しかし、私はWWW :: Mechanizeで同じことをする方法を見つけることができません。

$mech->post("https://" . $server . "/upload", Content_Type => 'multipart/form-data', Content => [upID => $upid, name => $dlfile, userID => 0, userK => 0, file_0 => [$dlfile]]); 

これは、大きなfatエラーメッセージで同様のjson応答を受信します。

Transfer-Encodingヘッダーを明示的に設定する必要がありますか?それにいくつかのトリックがありますか? Googleはこれについて多くの光を漏らしていないし、Perlmonksもそうではなく、ドキュメンテーションはちょっと鈍い。

+0

コールバックが使用されるのは、コンテンツの長さが事前にわかっているためで、コンテンツの長さがわかっている場合はチャンクエンコーディングを使用する必要がないからです。 – ikegami

答えて

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; 
+0

ありがとうございます、この解決策は正しく動作するようです... jsonの応答にはエラーがありません。私はまだ(前の)エラーの他にいくつかのことを理解していますが、今は残りを得ることができると思います。 –

4

本当にWWW::Mechanizeが必要ですか? LWP::UserAgentのサブクラスで、フォームの記入と送信、リンクのクリック、「戻る」操作などのページ履歴など、ブラウザのような機能を提供します。そのすべてを必要としない場合は、 LWP::UserAgentを使用する直接

いずれにせよ、post方法はLWP::UserAgentからそのまま継承され、そしてそれはあなたが

チャンクPOSTがへの参照にContentを設定することで送信する方法を行っているとして、それを直接使用するように罰金ですサブルーチン。サブルーチンは呼び出されるたびにデータの次のチャンクを返さなければなりません。最後に空の文字列またはを返します。

それは、このすべてがテストされていないことに注意してください。そして、あなたはpost

my $payload = to_json(...); 

$mech->post(
    "https://$server/upload", 
    Content_Type => 'multipart/form-data', 
    Content  => make_callback($payload) 
); 

このような

を呼び出すことができます。この

sub make_callback { 
    my ($data) = shift; 
    sub { substr($data, 0, 512, "") } 
} 

のように、クロージャを返すファクトリサブルーチンを書くのは簡単です

+0

私はLWPを直接使っても構いませんが、curlコマンドを使ってsystem()を使いたいとは思っていませんし、既にPythonなどの大きなスクリプトを書き直したいというわけでもありません。ありがたいことに、私はそれを試してみるつもりです。私が開発ツールで見ていたことに沿って試してみると、あなたがそれを指摘するまで、これがどのように機能するのか分かりませんでした。 –

+0

ファイルの内容以外の他のフィールドでこれを行う方法はありますか?私はファイルをアップロードすることができますが、他のいくつかの欠けている値が(私が知る限りでは)不安定になります。 –

関連する問題