Dynamic tar/archive creation in Mojolicious

56 views Asked by At

I have a directory of uploaded files, and I want to the user to download all files as an archive/tar. This is what I have implemented so far:

get '/admin/downloadmedia' => sub {
    my $c = shift;

    my $tar = Mojo::Tar->new;

    my $cb = $tar->files( [ glob('../files/*') ] )->create;
    warn Dumper( $tar->files );
    my $drain;
    $drain = sub {
        my $me = shift;
        return $me->finish if ( $tar->is_complete );
        my $chunk = $cb->();

        $me->write( $chunk, $drain );
    };

    $c->res->content->headers->add( 'Content-Type',        'application/tar' );
    $c->res->content->headers->add( 'Content-Disposition', 'attachment;filename=Zahaan-Bday-Media.tar' );

    $c->$drain;
};

I am behind a proxy sever (Caddy). Downloaded file is correctly identified as tar.

$ file Downloads/Zahaan-Bday-Media\ \(1\).tar                                                                                                                                                                              
Downloads/Zahaan-Bday-Media (1).tar: POSIX tar archive

But archive utility throws an error and is unable to open. Unable to understand whats wrong.

1

There are 1 answers

1
Maksym On

did you try to download the tar file directly (without going through the proxy) and see if it opens correctly.

You can try to debug it this way

use Mojo::Tar;

get '/admin/downloadmedia' => sub {
    my $c = shift;

    my $tar = Mojo::Tar->new;
    my $cb  = $tar->files([glob('../files/*')])->create;

    unless ($tar->is_complete) {
        $c->render(text => "error creating tar-archive: " . $tar->error, status => 500);
        return;
    }

    $c->res->content->headers->add('Content-Type',        'application/tar');
    $c->res->content->headers->add( 'Content-Disposition', 'attachment;filename=Zahaan-Bday-Media.tar' );


    my $drain;
    $drain = sub {
        my $me = shift;
        return $me->finish if ($tar->is_complete);
        my $chunk = $cb->();

        $me->write($chunk, $drain);
    };

    $c->$drain;
};