代码之家  ›  专栏  ›  技术社区  ›  cgp

在纯Perl中,从另一个HTTP资源流式传输最简单的方法是什么?

  •  6
  • cgp  · 技术社区  · 15 年前

    在Perl中,从另一个HTTP资源流式传输最简单的方法是什么(无需打开shell进行curl和读取stdin)?我在这里假设我正在读取的HTTP资源是一个潜在的无限流(或者非常非常长)

    4 回复  |  直到 15 年前
        1
  •  6
  •   Sinan Ünür    15 年前

    HTTP::Lite request 方法允许您指定回调。

    这个 $data_callback 参数(如果使用)是一种在接收数据时过滤数据或处理大型传输的方法。它必须是一个函数引用,并且将被传递:一个对进行回调的http请求实例的引用,一个对将要添加到主体中的当前数据块的引用,以及 $cbargs 参数(可以是任何参数)。它必须返回对要添加到文档正文中的数据的引用,或者返回undef。

    但从源头上看, 似乎 成为一只虫子 sub request 在这方面 似乎 忽略传递的回调。 似乎 set_callback :

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    use HTTP::Lite;
    
    my $http = HTTP::Lite->new;
    $http->set_callback(\&process_http_stream);
    $http->http11_mode(1);
    
    $http->request('http://www.example.com/');
    
    sub process_http_stream {
        my ($self, $phase, $dataref, $cbargs) = @_;
        warn $phase, "\n";
        return;
    }
    

    输出:

    C:\Temp> ht
    connect
    content-length
    done-headers
    content
    content-done
    data
    done
    

    方法的处理方式不同:

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    use HTTP::Lite;
    
    my $http = HTTP::Lite->new;
    $http->http11_mode(1);
    
    my $count = 0;
    $http->request('http://www.example.com/',
        \&process_http_stream,
        \$count,
    );
    
    sub process_http_stream {
        my ($self, $data, $times) = @_;
        ++$$times;
        print "$$times====\n$$data\n===\n";
    }
    
        2
  •  9
  •   Justin R.    15 年前

    好的旧LWP允许您将结果作为流进行处理。

    例如,这里有一个对yourFunc的回调,读取/传递byte_count字节到每个调用yourFunc(如果您不关心每个调用的数据有多大,只想尽快处理流,则可以删除该参数):

    use LWP;
    ...
    $browser = LWP::UserAgent->new();
    $response = $browser->get($url, 
                              ':content_cb' => \&yourFunc, 
                              ':read_size_hint' => byte_count,);
    ...
    sub yourFunc {
       my($data, $response) = @_;
       # do your magic with $data
       # $respose will be a response object created once/if get() returns
    }
    
        3
  •  3
  •   Andy Ross    15 年前

    open my $stream, "-|", "curl $url" or die;
    while(<$stream>) { ... }
    

    对我来说,这是最简单的方法。这当然比这里的其他建议更简单。。。

        4
  •  2
  •   Sinan Ünür    15 年前

    Event::Lib 将为您的平台提供一个最快的异步IO方法的简单接口。

    IO::Lambda 对于创建快速、响应迅速的IO应用程序来说,它也非常好。

        5
  •  0
  •   user3718260    5 年前

    这是我最后通过Net::HTTP使用的一个版本

    use Net::HTTP;
    
    my $s = Net::HTTP->new(Host => "www.example.com") || die $@;
    $s->write_request(GET => "/somestreamingdatasource.mp3");
    my ($code, $mess, %h) = $s->read_response_headers;
    while (1) {
      my $buf;
      my $n = $s->read_entity_body($buf, 4096);
      die "read failed: $!" unless defined $n;
      last unless $n;
      print STDERR "got $n bytes\n";
      print STDOUT $buf;
    }