Skip to content

Instantly share code, notes, and snippets.

@judofyr
Created February 11, 2013 15:42
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save judofyr/4e54fa2ca0bd1cfb344d to your computer and use it in GitHub Desktop.
Save judofyr/4e54fa2ca0bd1cfb344d to your computer and use it in GitHub Desktop.
Mojolicious meets Plupload
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