我可以使用HTTP :: Request :: Common :: post发送二进制变量吗?

问题描述 投票:0回答:1

我想发送我之前使用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);
perl http gzip
1个回答
4
投票

附注:预先声明变量,如

   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 documentationpost方法称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

© www.soinside.com 2019 - 2024. All rights reserved.