Send multipart request from ajax to spring controller without form?

2.8k views Asked by At

I am uploading an image from the desktop, and converting this image into base code in javascript. After that I want to send this image base code to spring controller with the multipart request. But I am not using Form.

HTML

 <input id="inputFileToLoad" type="file"  onchange="encodeImageFileAsURL()">   

JAVA SCRIPT

 window.photoCakeUrl = '<c:url value="/media/image/upload"/>';
      function encodeImageFileAsURL() {
                var filesSelected = document.getElementById("inputFileToLoad").files;
                if (filesSelected.length > 0) {
                    var fileToLoad = filesSelected[0];
                    var fileReader = new FileReader();
                    fileReader.onload = function (fileLoadedEvent) {
                        var srcData = fileLoadedEvent.target.result; // <--- data: base64
                        var newImage = document.createElement('img');
                        var photoCake = srcData;
                        newImage.src = srcData;
                        document.getElementById("imgTest").innerHTML = newImage.outerHTML;
                        var ajax1 = $.ajax({
                            type: 'POST',
                            url: photoCakeUrl,
                            processData: false, // important
                            contentType: false, // important
                            dataType: 'json',
                            data: {photoCak: photoCake}
                        });

                      });

                    },
                            fileReader.readAsDataURL(fileToLoad);
                }
            }

SPRING CONTROLLER:

@RequestMapping(value = "/media/image/upload", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, String> productPictureUploadnew(MultipartHttpServletRequest request, HttpServletResponse response) {
        Map<String, String> resp = new HashMap<>();
        String photoCake = request.getParameter("photoCak");


        System.out.println("photoCake   " + photoCake);

        return resp;
    }

But when I am generating AJAX call then 500 error will comes. If i am using simply

public Map<String, String> productPictureUploadnew(HttpServletRequest
 request, HttpServletResponse response)

Then it works. Mean when I am using MultipartHttpServletRequest place of HttpServletRequest request then it is not works.

3

There are 3 answers

0
Varun Sharma On BEST ANSWER

I got solution, We can use formData in javascript without using form in any JSP to send MultipartHttpServletRequest.

 window.photoCakeUrl = '<c:url value="/media/image/upload"/>';
      function encodeImageFileAsURL() {
                var filesSelected = document.getElementById("inputFileToLoad").files;
                if (filesSelected.length > 0) {
                    var fileToLoad = filesSelected[0];
                    var fileReader = new FileReader();
                    fileReader.onload = function (fileLoadedEvent) {
                        var srcData = fileLoadedEvent.target.result; // <--- data: base64
                        var newImage = document.createElement('img');
                        var photoCake = srcData;
                        newImage.src = srcData;
                        document.getElementById("imgTest").innerHTML = newImage.outerHTML;

                        var formData = new FormData();
                        formData.append("imgFile", document.getElementById("inputFileToLoad").files[0]);

                        var ajax1 = $.ajax({
                            type: 'POST',
                            url: photoCakeUrl,
                            dataType: 'json',
                            data: {photoCak: photoCake}
                        });

                      });

                    },
                            fileReader.readAsDataURL(fileToLoad);
                }
            }

var formData = new FormData();
formData.append("imgFile", document.getElementById("inputFileToLoad").files[0]);

Controller:

 @RequestMapping(value = "/media/image/upload", method = RequestMethod.POST)
        @ResponseBody
        public Map<String, String> productPictureUploadnew(MultipartHttpServletRequest request, HttpServletResponse response) {
            Map<String, String> resp = new HashMap<>();
            System.out.println("fsasasafsafsafsafsa");
            Iterator<String> itr = request.getFileNames();

            String photoCake = request.getParameter("photoCak");
            File file;
          ----------
           -------
          ----------              

            return resp;
        }

Thanks you, I hope this is help full for you guys.

0
Vinay On

You are sending it as multipart/form-data may be that's why HttpServletRequest isn't able to get your data , remove contentType option from ajax call then jquery will use the defaylt wiz. 'application/x-www-form-urlencoded; charset=UTF-8'

var ajax1 = $.ajax({
                       type: 'POST',
                        url: photoCakeUrl,
                        processData: false, // important
                        dataType: 'json',
                        data: {photoCak: photoCake}
                    });
0
Endless On

This is how I would have done it:

window.photoCakeUrl = '<c:url value="/media/image/upload"/>';
window.URL = window.URL || window.webkitURL

function encodeImageFileAsURL() {
  var filesSelected = $('#inputFileToLoad')[0].files;

  if (filesSelected.length) {
    var fileToLoad = filesSelected[0];
    var img = new Image();
    var formData = new FormData();

    formData.append('imgFile', fileToLoad);

    img.onload = function() {
      // only append the image once it's loaded so we don't append broken images
      $('#imgTest').html(this);
      URL.revokeObjectURL(this.src); // Release memory
      // Uploading a image when we can ensure it's a image that can be loaded
      fetch(photoCakeUrl, {method: 'POST', body: formData});
    }

    img.onerror = function() {
      // You didn't upload a image
    }

    img.src = URL.createObjectURL(srcData);
  }
}
  • URL.createObjectURL is faster and uses less memory then a long base64 string that is also ~3x larger in size and uses 2x more memory since it's stored in utf16 and not utf8
  • You can use new Image which is a nicer sorter version of createElement('img')
  • Then I would also use Fetch instead of $.ajax cuz jQuery handle formData stupidly (need to set processData & contentType to false)
  • Then i would also add the accept="images/*" attribute to the file input to filter out images