【问题标题】:Can I send a binary variable using HTTP::Request::Common::post?我可以使用 HTTP::Request::Common::post 发送二进制变量吗?
【发布时间】:2018-03-06 12:35:41
【问题描述】:

我想通过帖子发送我之前用 gzip 压缩过的数据 请求而不将其保存到文件中。 在 HTTP::Request::Common 的文档中,我没有看到任何地方解释了如何发布我之前制作的压缩数据。

I want to emulate this call,
curl -F "file0=@+Wowhead_Looter.lua.gz" -F "file1=@creaturecache.wdb.gz" -F "file2=@gameobjectcache.wdb.gz" \
     -F "file3=@itemcache.wdb.gz" -F "file4=@pagetextcache.wdb.gz" \
     -F "file5=@questcache.wdb.gz" "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】:

旁注:预先声明变量,如

   my ($wdb_dir,
       $wdb_dir_dh,
       @wdb_dir_files,
       $file,
       $vol,
       $dir,
       $ffile,
       %gzipped_wdb);

被认为是糟糕的风格。变量应该在尽可能小的范围内声明,这通常意味着它应该在第一次使用时声明。

(另外,3 个空格的缩进很奇怪。)


根据the curl manual-F 指定用于提交 Web 表单的字段(特别是 multipart/form-data 格式)。以@ 为前缀的值使 curl 上传文件(附加到 POST 请求)。

LWP::UserAgent documentation 表示post 方法在下面调用HTTP::Request::Common::POST

HTTP::Request::Common documentation for POST 表示您可以通过将内容类型指定为'form-data' 来创建multipart/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 的文件(因为我们不想从磁盘读取真正的文件),上传文件名$_(这是我们希望网络服务器看到的文件名; 也许你想在这里传递"$_.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
}

然后在post 调用中传递Content => \@fields

【讨论】:

  • Re "另外,3 个空格的缩进很奇怪", :p
  • 感谢您的详细解释。最后一个是我使用的解决方案。 3 个空格的缩进是从 emacs 中设置的,In 只是一直使用它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-13
  • 2011-11-17
  • 2017-05-05
  • 2012-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多