Search code examples
javajqueryajaxcanvasjcrop

How to submit file from form using ajax in java config spring?


Hi I'm trying to upload a image file to the server.I have used jCrop to crop the image before uploading and used canvas to get the cropped image coordinates.I have included controller and jsp files .But I'm not able to send formdata using ajax.

AppController.java

@RequestMapping(value = "/upload", method = RequestMethod.POST)
public String handleFormUpload(@RequestParam("file") MultipartFile file, ModelMap model) throws IOException{
if (!file.isEmpty()) {
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
     String name = auth.getName(); //get logged in username
     BufferedImage src = ImageIO.read(new ByteArrayInputStream(file.getBytes()));
     File destination = new File("/home/me/Desktop/"+name+".png");
     model.addAttribute("username", name);
     // something like C:/Users/tom/Documents/nameBasedOnSomeId.png
     ImageIO.write(src, "png", destination);
     //Save the id you have used to create the file name in the DB. You can retrieve the image in future with the ID.
    }else {
     System.out.println("file is empty");
    }
return "prefs";
}

prefs.jsp

<script type="text/javascript">
$(function(){
    $('.majorpoints').click(function(){
        $(this).find('.hiders').slideToggle();
    });
     $("#imgInp").change(function(){
         var c = $('.cropArea').Jcrop({

             onSelect: updateCoords,

                   bgOpacity:   .4,
                   setSelect:   [ 100, 100, 50, 50 ],
                   aspectRatio: 16 / 9
           });

         function readURL(input) {

                if (input.files && input.files[0]) {
                    var reader = new FileReader();

                    reader.onload = function (e) {
                        $('#blah').attr('src', e.target.result);
                    }

                    reader.readAsDataURL(input.files[0]);
                }
            }
            readURL(this);
        }); 

     $('#btnCrop').click(function () {
            var x1 = $('#x').val();
            var y1 = $('#y').val();
            var width = $('#w').val();
            var height = $('#h').val();
            var canvas = $("#canvas")[0];
            alert(x1+""+y1+""+""+width+""+height);
            var context = canvas.getContext('2d');
            var img = new Image();
            img.onload = function () {
                canvas.height = height;
                canvas.width = width;
                context.drawImage(img, x1, y1, width, height, 0, 0, width, height);
                $("#imgInp").val(canvas.toDataURL("image/jpeg")); 
            };

            var data = new FormData();
            data.append('file', dataURItoBlob(canvas.toDataURL("image/jpeg")));
            $.ajax({
                url: 'upload',
                data: data,
                contentType: false,
                processData: false,
                type: 'POST',
                success: function(data){
                    alert(data);
                }
            }); 

            img.src = $('#blah').attr('src');

        });
});
 function dataURItoBlob(dataURI) {
    // convert base64/URLEncoded data component to raw binary data held in a string
    var byteString;
    if (dataURI.split(',')[0].indexOf('base64') >= 0)
        byteString = atob(dataURI.split(',')[1]);
    else
        byteString = unescape(dataURI.split(',')[1]);

    // separate out the mime component
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

    // write the bytes of the string to a typed array
    var ia = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }

    return new Blob([ia], {type:mimeString});
}
function updateCoords(c)
  {
    console.log(c);
    $('#x').val(c.x);
    $('#y').val(c.y);
    $('#w').val(c.w);
    $('#h').val(c.h);
    $('#btnCrop').show();
  };
 </script>


<div id="myModal" class="modal fade" role="dialog">
      <div class="modal-dialog">

        <!-- Modal content-->
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal">&times;</button>
            <h4 class="modal-title">Modal Header</h4>
          </div>
          <div class="modal-body">
            <form method="POST" action="upload" enctype="multipart/form-data">
                Please select a file to upload : 
                <input type="file" name="file" class="file" id="imgInp" />
                <div class="cropArea">
                    <img id="blah" src="#" alt="your image" />
                </div>
                <input type="hidden" id="x" name="x" />
                <input type="hidden" id="y" name="y" />
                <input type="hidden" id="w" name="w" />
                <input type="hidden" id="h" name="h" />
                <canvas id="canvas" height="5" width="5"></canvas>

            </form>
             <input type="button" id="btnCrop" value="Crop" style="display: none" />
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
          </div>
        </div>

      </div>
</div>

Solution

  • You are missing this param

    enctype: 'multipart/form-data'

    $.ajax({
            url: 'upload',
            data: data,
            contentType: false,
            processData: false,
            enctype: 'multipart/form-data',
            type: 'POST',
            success: function(data){
                       alert(data);
                    }
           });
    

    You should have this

    var data = new FormData();
    data.append('file', jQuery('#imgInp')[0].files[0]);
    

    instead of

    jQuery.each(jQuery('#imgInp')[0].files, function(i,file) {
                data.append('file-'+i, file);
            });
    

    Later Edit 2: in your function dataURItoBlob(dataURI) add callback like this:

    function dataURItoBlob(dataURI, callback) {
       ...
     callback();
    }
    

    then in

    $('#btnCrop').click(function () { ...

    data.append('file', dataURItoBlob(canvas.toDataURL("image/jpeg", function(){
                $.ajax({
                    url: 'upload',
                    data: data,
                    contentType: false,
                    processData: false,
                    type: 'POST',
                    success: function(data){
                        alert(data);
                    }
                }); 
      })));
    

    this way, you are sure that you make the ajax call after dataURItoBlob is executed.