2017-03-02 29 views
3

나는 특정 웹 서비스를 사용하려고 시도하는거야, 나는 성공적으로 다음과 같은 명령을 사용하여 업로드를 수행 할 수 있습니다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 헤더를 먼저 명시 적으로 설정해야합니까? 다른 트릭이 있습니까? 구글은 이것에 대해 많은 것을 밝히지 않았고, 펄크 몬스터도 아니다. 그리고 문서는 약간 둔하다.

+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을 설정하는 것입니다 보낼 수있는 방법을했던 것처럼 직접 사용하는 괜찮습니다 서브 루틴. 서브 루틴은 호출 할 때마다 데이터의 다음 덩어리를 반환해야하고, 더 이상 보낼 문자열이 없으면 undef을 반환해야합니다.

데이터가 JSON 문자열로 간주됩니까?

그런 다음 당신이 좋아하는 post를 호출 할 수 있습니다이

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

같은 폐쇄를 반환하는 공장 서브 루틴을 작성하는 가장 쉬운 방법이

my $payload = to_json(...); 

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

이 모든 테스트되지 않은 것을 유의하십시오

+0

LWP를 직접 사용해도 괜찮습니다. 나는 curl 명령을 사용하여 system()을 사용하고 싶지 않으며, 이미 파이썬이나 다른 것의 큰 스크립트를 다시 작성하고 싶지 않습니다. 고마워, 그걸로 고칠거야. dev 도구에서 보았던 것을 따라 가려고했는데, 당신이 그것을 지적하기 전까지 이것이 어떻게 작동하는지 이해하지 못했다고 생각합니다. –

+0

파일 내용 외에 다른 필드를 사용하여이 작업을 수행 할 수 있습니까? 파일을 업로드 할 수는 있지만 다른 누락 된 값이 있습니다 (내가 말할 수있는 것만 큼). –