I compared the VERSION1: standard html file upload with VERSION2: a html5 fileApi and ajax upload. It turns out that the html5 fileApi and ajax upload is much much slower than the old html file upload.
- Why is the upload in version 2 so much slower than in version1?
 - How can I accelerate the upload in version2?
 
VERSION1:
HTML
<g:form method="post" accept-charset="utf-8" enctype="multipart/form-data"  
     name="imageUploaderForm" id="imageUploaderForm" url="someurl">
    <input type="file" accept="image/jpeg, image/gif, image/png" 
            name="image" id="image" />
</form>
JS (I use JQueryForm)
$("#image").change(function() {
  $("#imageUploaderForm").ajaxForm({
    complete: function(response){
        console.log("upload complete");
    }
  });
  $("#imageUploaderForm").submit();
});
Server code Grails 2.2.4:
CommonsMultipartFile file = (CommonsMultipartFile) request.getFile('image')
byte [] imageBytes = file.getBytes()
VERSION2:
HTML
<g:form method="post" accept-charset="utf-8" enctype="multipart/form-data"  
         name="imageUploaderForm" id="imageUploaderForm" url="someurl"></form>
<input id="UploadFileInput" class="UploadFileInput" type="file" name="image" accept="image/jpeg, image/gif, image/png" />
JS (I use filereader.js which just wraps the filereader api for jquery) I loaded the uploaded image into a html5 canvas because I need to manipulate the image before uploading.
var fileReaderOpts = {
        readAsDefault: 'BinaryString',
        on: {
            load: function(event, file) {
                var $img = $('<img>'), 
                    imgWidth, imgHeight;
                $img.load(function() {
                    // Create the canvas.
                    $originalCanvas = $('<canvas data-caman-hidpi-disabled>');
                    var originalContext = $originalCanvas[0].getContext('2d');  
                    // Save image to canvas
                    $originalCanvas[0].width = this.width;
                    $originalCanvas[0].height = this.height;
                    originalContext.drawImage(this, 0, 0);
                    // some image modification on the canvas
                    // send image to server
                    var imageUrl = $originalCanvas[0].toDataURL();
                    $("#imageUploaderForm").ajaxForm({
                        data: { 
                            img : imageUrl,
                        },
                        complete: function(response){
                                console.log("upload complete");
                        } 
                    }); 
                    $("#imageUploaderForm").submit();
                }); // end $img.load
                // Set the src of the img, which will trigger the load event when done
                $img.attr('src', event.target.result);
            },// end load           
            beforestart: function(file) {
                // Accept only images. Returning false will reject the file.
                return /^image/.test(file.type);
            }
        }
};
// Bind the fileReader plugin the upload input and the drop area.
$("UploadFileInput").fileReaderJS(fileReaderOpts);
Server code Grails 2.2.4:
String imgBase64 = params.image
imgBase64 = imgBase64.trim().replaceFirst("data:image/png;base64,", "")
byte[] imageBytes = Base64.decode(imgBase64.getBytes())
Here is what I have measured:
I have uploaded a jpg image with 7.5MB size with both version1 and version2, and also with pinterest and flickr. I started the timer for version1 and version2 after the image has been processed on the client side at the moment where the form is submitted.
Note: The canvas-related code is not included in the time. I started after this with the measuring.
The result:
- version1: 1.16 min
 - version2: 3.43 min
 - pinterest: 1.09 min
 - flickr: 1.11 min