-
-
Save judofyr/4e54fa2ca0bd1cfb344d to your computer and use it in GitHub Desktop.
Mojolicious meets Plupload
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package Mojolicious::Plugin::Plupload; | |
use Mojo::Base 'Mojolicious::Plugin'; | |
use File::Copy 'move'; | |
use File::Path 'mkpath'; | |
has 'directory'; | |
sub register { | |
my ($self, $app, $config) = @_; | |
$self->{$_} = $config->{$_} for keys %$config; | |
# Make sure the dircetory is present. | |
mkpath($self->directory); | |
$app->routes->post($config->{path}, sub { $self->upload(@_) }); | |
$app->helper(plupload_expand_path => sub { | |
$self->expand_path(pop); | |
}); | |
} | |
sub expand_path { | |
my ($self, $name) = @_; | |
$name //= "tmp"; | |
$name =~ s/[^\w\._]+/_/g; | |
$self->directory."/".$name; | |
} | |
sub upload { | |
my ($self, $c) = @_; | |
$c->res->headers->content_type('text/plain'); | |
my $fail = sub { | |
my ($code, $msg) = @_; | |
$c->render(status => 500, json => { | |
jsonrpc => "2.0", | |
error => { code => $code, message => $msg }, | |
id => "id" | |
}); | |
}; | |
my $path = $self->expand_path($c->param('name')); | |
my $chunk = $c->param('chunk') // 0; | |
my $chunks = $c->param('chunks') // 1; | |
if (-f $path) { | |
return $fail->(100, "File already exists"); | |
} | |
# Unfinished uploads are stored with a .part extension. | |
my $part_path = $path.".part"; | |
my $asset; | |
if ($c->req->is_multipart) { | |
my $file = $c->param('file'); | |
$asset = $file->asset; | |
} else { | |
$asset = $c->req->content->asset; | |
} | |
if ($chunk == 0) { | |
# The first chunk; let's just move it over. | |
$asset->move_to($part_path); | |
} else { | |
# All other chunks are appended. | |
open(my $fh, ">>", $part_path); | |
my $size = $asset->size; | |
my $offset = 0; | |
# Read the upload file chunk for chunk. | |
while ($offset < $size) { | |
my $chunk = $asset->get_chunk($offset); | |
$offset += length($chunk); | |
# Append | |
print $fh, $chunk; | |
} | |
close($fh); | |
} | |
# Final chunk | |
if ($chunk == $chunks - 1) { | |
# Rename .part to proper path. | |
move($part_path, $path); | |
} | |
$c->render(json => { | |
jsonrpc => "2.0", | |
result => undef, | |
id => "id" | |
}); | |
} | |
1; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment