perlでサイズが大きいファイルをhttp postする

perlでサイズが大きいファイルをhttp post or putするには下記のようにするとよさそう。

LWP, HTTP::Tinyともrequest contentとしてcallbackを指定できるのでそれを使う。 ただし、デフォルトだとTransfer-Encoding: chunkedになるので明示的にContent-Lengthを指定するとよさげ。

use strict;
use warnings;
use HTTP::Tiny;
use LWP::UserAgent;

my $read_callback = sub {
    my $fh = shift;
    sub {
        my $len = read $fh, my $buf, 32768;
        if (!defined $len) {
            die "read error: $!";
        } elsif ($len == 0) {
            undef; # EOF, finish
        } else {
            $buf;
        }
    };
};

my $url = "http://example.com";
my $file = "bigfile.data";
open my $fh, "<", $file or die;
binmode $fh;

# HTTP::Tiny
my $tiny = HTTP::Tiny->new;
my $res_tiny = $tiny->post($url, {
    headers => {
        'Content-Length' => -s $fh,
        'Content-Type'   => "application/octet-stream"
    },
    content => $read_callback->($fh),
});

seek $fh, 0, 0; # rewind

# LWP
my $lwp = LWP::UserAgent->new;
my $req = HTTP::Request->new(
    POST => $url,
    [ 'Content-Length' => -s $fh, 'Content-Type' => "application/octet-stream" ],
    $read_callback->($fh),
);
my $res_lwp = $lwp->request($req);

前記事を真似れば、upload speed制限(limit 5Mbpsとか) もできそうではある。