perl – www :: curl – 如何上传(发布)大文件

我使用WWW :: Curl上传文件

use WWW::Curl::Easy 4.14;
use WWW::Curl::Form;

my $url = 'http://example.com/backups/?sid=12313qwed323';
my $params = {
    name => 'upload',action => 'keep',backup1 => [ '/tmp/backup1.zip' ],# 1st file for upload
};

my $form = WWW::Curl::Form->new();
foreach my $k (keys %{$params}) {
    if (ref $params->{$k}) {
        $form->formaddfile(@{$params->{$k}}[0],$k,'multipart/form-data');
    } else {
        $form->formadd($k,$params->{$k});
    }
}

my $curl = WWW::Curl::Easy->new() or die $!; 
$curl->setopt(CURLOPT_HTTPPOST,$form);
$curl->setopt(CURLOPT_URL,$url);

my $body;   
$curl->setopt(CURLOPT_WRITEDATA,\$body);
my $retcode = $curl->perform();
my $response_code = $curl->getinfo(CURLINFO_HTTP_CODE);

没什么特别的,这个代码效果很好.

我想上传文件,我不想预先加载内存中的所有内容.至少这是我听说libcurl正在做的事情.

CURLOPT_READFUNCTION接受返回部分内容的回调.这意味着我不能使用WWW :: Curl :: Form来设置POST参数,但我必须通过此回调返回整个内容.是对的吗?

我认为代码看起来像这样:

use WWW::Curl::Easy 4.14;

my $url = 'http://example.com/backups/?sid=12313qwed323'
my $params = {
    name => 'upload',# 1st file for upload
};

my $fields;
foreach my $k (keys %{$params}) {
    $fields .= "$k=".(ref $params->{$k} ? '@'.@{$params->{$k}}[0] : uri_escape_utf8($params->{$k}))."&";
}
chop($fields);

my $curl = WWW::Curl::Easy->new() or die $!;
$curl->setopt(CURLOPT_POST,1);
$curl->setopt(CURLOPT_POSTFIELDS,$fields); # is it needed with READFUNCTION??
$curl->setopt(CURLOPT_URL,$url);

my @header = ('Content-type: multipart/form-data','transfer-encoding: chunked');
$curl->setopt(CURLOPT_HTTPHEADER,\@header);

#$curl->setopt(CURLOPT_INFILESIZE,$size);
$curl->setopt(CURLOPT_READFUNCTION,sub {

    # which data to return here?
    # $params (without file) + file content?

    return 0;
});

CURLOPT_READFUNCTION回调必须返回哪些数据? $params文件内容?格式是什么?

我是否真的必须自己创建数据(由CURLOPT_READFUNCTION返回),还是有一种简单的方法以正确的格式创建它?

谢谢

解决方法

测试 16formpost.t是相关的.如您所见,它已完全禁用.这个事实以及我对回调函数的各种返回值的无结果实验让我相信在Perl绑定中已经破解了CURLOPT_READFUNCTION功能.

I have to return the whole content through this callback. Is that right?

不,你可以分段地提供请求体,适合分块编码.根据CURLOPT_INFILESIZE中设置的限制,回调将被多次调用.

Which data does CURLOPT_READFUNCTION callback have to return?

HTTP请求正文.由于您执行文件上载,这意味着Content-Type multipart/form-data.以下是使用HTTP :: Message的示例. CURLOPT_HTTPPOST是构建此格式的另一种方法.

use HTTP::Request::Common qw(POST);
use WWW::Curl::Easy 4.14;

my $curl = WWW::Curl::Easy->new or die $!;
$curl->setopt(CURLOPT_POST,1);
$curl->setopt(CURLOPT_URL,'http://localhost:5000');
$curl->setopt(CURLOPT_HTTPHEADER,[
    'Content-type: multipart/form-data','transfer-encoding: chunked'
]);
$curl->setopt(CURLOPT_READFUNCTION,sub {
    return POST(undef,Content_Type => 'multipart/form-data',Content => [
        name    => 'upload',action  => 'keep',# 1st file for upload
    ])->content;
});
my $r = $curl->perform;

相关文章

1. 如何去重 #!/usr/bin/perl use strict; my %hash; while(...
最近写了一个perl脚本,实现的功能是将表格中其中两列的数据...
表的数据字典格式如下:如果手动写MySQL建表语句,确认麻烦,...
巡检类工作经常会出具日报,最近在原有日报的基础上又新增了...
在实际生产环境中,常常需要从后台日志中截取报文,报文的形...
最近写的一个perl程序,通过关键词匹配统计其出现的频率,让...