Perl LWP POST上传的进度指示器

时间:2014-07-08 11:57:29

标签: perl upload statusbar lwp

我正在处理Perl脚本,该脚本使用POST请求上传大文件。我的问题是,是否有可能有状态输出,因为上传大文件可能需要一些时间与我的互联网连接。

我的意思是像

的状态栏
$| = 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"

1 个答案:

答案 0 :(得分:5)

如果您查看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;
}