【问题标题】:Progress indicator for Perl LWP POST uploadPerl LWP POST 上传的进度指示器
【发布时间】:2014-07-08 11:57:28
【问题描述】:

我正在编写一个通过 POST 请求上传大文件的 Perl 脚本。我的问题是是否可以输出状态,因为上传大文件可能需要一些时间来连接我的互联网。

我的意思是像一个状态栏

$| = 1;
print "\r|---------->                   | 33%";
print "\r|-------------------->         | 66%";
print "\r|------------------------------| 100%\n";

这是我的上传代码:

my $ua=LWP::UserAgent->new();
$file = "my_big_holyday_vid.mp4";

$user = "username";
$pass = "password";

print "starting Upload...\n";
$res = $ua->post(
                  "http://$server",
                  Content_Type => 'form-data',
                  Content =>[
                    fn => ["$file" => $file],
                    username => $user,
                    password => $pass,
                  ],
                );
print "Upload complete!\n"

【问题讨论】:

  • 您确定您的fn 字段正确吗? "$file" 等同于 $file 的简单字符串,因此您传递的是 fn => [$file, $file]

标签: perl upload statusbar lwp


【解决方案1】:

如果您查看HTTP::Request::Common 的文档,您会发现,如果您将$HTTP::Request::Common::DYNAMIC_FILE_UPLOAD 设置为true 值,那么请求对象的content 方法将提供一个回调,即用于分块获取数据。

通常每次上传需要更多数据时都会调用它,但您可以将其包装在自己的子例程中以监控上传进度。

下面的程序给出了一个例子。如您所见,创建了HTTP::Request 对象(我假设fn 字段应该只是[$file])并使用content 方法获取回调子例程。

子程序wrapper 只是在第一行调用$callback 来获取下一个数据块,并在最后一行返回它,就像$callback 本身一样。在这两行之间,您可以添加您喜欢的内容,只要它不会干扰将块传递回 LWP。在这种情况下,我已经打印了每个块的大小以及到目前为止每次调用的上传百分比。

出于百分比计算的目的,文件的完整大小可作为$req->header('content-length') 访问,这比在文件上使用-s 更正确。

此外,必要时可以检测到最终迭代,因为回调将返回大小为零的块。

请注意,这是未经测试的,除非它可以编译并且大致正确,因为我没有需要上传文件的互联网服务。

use strict;
use warnings;

use LWP;
use HTTP::Request::Common;
$HTTP::Request::Common::DYNAMIC_FILE_UPLOAD = 1;

my $ua = LWP::UserAgent->new;

my $server        = 'example.com';
my $file          = 'my_big_holyday_vid.mp4';
my ($user, $pass) = qw/ username password /;

print "Starting Upload...\n";

my $req = POST "http://$server",
  Content_Type => 'form-data',
  Content => [
    fn => [$file],
    username => $user,
    password => $pass,
  ];

my $total;
my $callback = $req->content;
my $size = $req->header('content-length');
$req->content(\&wrapper);
my $resp = $ua->request($req);

sub wrapper {
  my $chunk = $callback->();

  if ($chunk) {
    my $length = length $chunk;
    $total += $length;
    printf "%+5d = %5.1f%%\n", $length, $total / $size * 100;
  }
  else {
    print "Completed\n";
  }

  $chunk;
}

【讨论】:

  • 非常感谢,太好了!有没有办法设置块大小?因为小块大小将整体上传速度降低到原来的 1/3...
  • 什么是“原版”?听起来您根本不需要原来的 HTTP::Request::Common 行为!可能您不需要使用原始的$callback 来获取要发送的每个块,因此您可以打开文件并自己调用read,但如果不检查模块代码,我无法确定。我会看看HTTP::Request::StreamingUpload,因为它似乎可以在没有任何黑客的情况下做你想做的事
猜你喜欢
  • 2021-01-02
  • 2016-06-13
  • 2019-03-06
  • 2011-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-23
相关资源
最近更新 更多