#!/usr/bin/perl

use strict;
use warnings;
use utf8;
use feature ':5.10';

use Mojolicious::Lite;
use Scalar::Util 'weaken';

use Digest::MD5;

my $sum;
my $md5;

# Intercept multipart uploads and log each chunk received
hook after_build_tx => sub {
  my $tx = shift;

  $sum = 0;
  $md5 = Digest::MD5->new;

  # Subscribe to "upgrade" event to identify multipart uploads
  weaken $tx;
  $tx->req->content->on(upgrade => sub {

    my ($single, $multi) = @_;
    return unless $tx->req->url->path->contains('/upload');

    # Subscribe to "part" event to find the right one
    $multi->on(part => sub {
      my ($multi, $single) = @_;

      # Subscribe to "body" event of part to make sure we have all headers
      $single->on(body => sub {
        my $single = shift;

        app->log->debug( $single->headers->content_disposition );

        # Make sure we have the right part and replace "read" event
        return unless $single->headers->content_disposition =~ /example/;
        $single->unsubscribe('read')->on(read => sub {
          my ($single, $bytes) = @_;

          $md5->add( $bytes );
	  $sum += length($bytes);

          # Log size of every chunk we receive
          app->log->debug(length($bytes) . ' bytes uploaded, ' .$sum. ' total');
        });
      });
    });
  });
};

# Upload form in DATA section
get '/' => 'index';

# Streaming multipart upload
post '/upload' => sub {
	my $c = shift;

	my $digest = $md5->hexdigest();
	app->log->debug( 'md5: ' . $digest );
	$c->render( text => $digest );
};

app->max_request_size( 1024 * 1024 *1024 );

app->start;
__DATA__

@@ index.html.ep
<!DOCTYPE html>
<html>
  <head><title>Streaming multipart upload</title></head>
  <body>
    %= form_for upload => (enctype => 'multipart/form-data') => begin
      %= file_field 'example'
      %= submit_button 'Upload'
    % end
  </body>
</html>
