我想发送我之前使用gzip压缩的数据和post请求,而不将其保存到文件中。在HTTP :: Request :: Common的文档中,我看到没有解释如何发布我之前创建的压缩数据。
I want to emulate this call,
curl -F "file0=@+Wowhead_Looter.lua.gz" -F "[email protected]" -F "[email protected]" \
-F "[email protected]" -F "[email protected]" \
-F "[email protected]" "URL"
我不知道这是一个电话还是多个电话。
有人可以帮我吗?
我有这个函数读取所有文件并返回包含所有压缩文件的对象:
sub compress_wdb
{
my ($wdb_dir,
$wdb_dir_dh,
@wdb_dir_files,
$file,
$vol,
$dir,
$ffile,
%gzipped_wdb);
$wdb_dir = shift;
opendir $wdb_dir_dh, $wdb_dir,;
@wdb_dir_files = grep(/^.+\..+$/, readdir $wdb_dir_dh);
closedir $wdb_dir_dh;
for $file (@wdb_dir_files)
{
gzip $wdb_dir."/".$file => \$gzipped_wdb{$file}
or die "gzip failed: $GzipError\n";
}
return %gzipped_wdb;
}
该函数后来被调用如下:
my %wdb = compress_wdb($wdb_dir);
然后是post函数,我有问题:
sub post
{
my ($auth_user, $auth_password, $data, $ua, $req);
$ua = LWP::UserAgent->new;
$req = $ua->post("URL",
Content_Type => 'form-data',
Content => [
# $addon => [ $obj ],
],
);
}
比这更像是这样的:
post(\%wdb);
附注:预先声明变量,如
my ($wdb_dir,
$wdb_dir_dh,
@wdb_dir_files,
$file,
$vol,
$dir,
$ffile,
%gzipped_wdb);
被认为是不好的风格。变量应该在尽可能小的范围内声明,这通常意味着它应该在第一次使用时声明。
(另外,3个空格缩进很奇怪。)
根据the curl
manual,-F
指定了网络表单提交的字段(具体地,以multipart/form-data
格式)。以@
为前缀的值使curl上传文件(附加到POST请求)。
LWP::UserAgent
documentation说post
方法称HTTP::Request::Common::POST
在下面。
HTTP::Request::Common
documentation for POST
说你可以通过将内容类型指定为multipart/form-data
来创建'form-data'
请求。它还说您可以通过将数组引用指定为表单字段值来执行文件上载,并且可以通过设置Content
伪标头(绕过从磁盘读取实际文件)来创建“虚拟文件”。
把它们放在一起:
sub post
{
my ($files) = @_;
my $ua = LWP::UserAgent->new;
my $response = $ua->post(
"YOUR URL HERE",
Content_Type => 'form-data',
Content => [
do {
my $i = 0;
map +(
'file' . $i++ => [ undef, $_, Content => $files->{$_} ]
),
sort keys %$files
}
],
);
...
}
我们迭代%$files
的键,我假设它是压缩文件的短名称。 (我们也按字母顺序执行以使其具有确定性,这通常适用于调试。)
我们还维护一个计数器($i
),我们用它来生成表单字段名称。
对于每个文件名(由$_
存储在map
中),我们生成一个键值对。关键是表单字段名称(由field
和当前计数器值组成),值是数组引用(这是我们的文件上载规范)。
数组引用包含一个undef
文件(因为我们不想从磁盘读取真实文件),$_
的上传文件名(这是我们希望Web服务器看到的文件名;也许你想通过"$_.gz"
这里?),以及最重要的部分,存储在$files->{$_}
下的实际内容。
所有这一切都发生在post
的调用中,这要归功于do
块,这无疑是厚颜无耻的。您也可以事先创建数据结构:
my @fields;
for my $name (sort keys %$files) {
push @fields, 'file' . @fields => [ undef, $name, Content => $files->{$name} ];
# we don't need a counter here because we can just ask @fields how big it is
}
然后在Content => \@fields
电话中传递post
。