将多部分请求从 ajax 发送到 spring 控制器但没有表格?

Send multipart request from ajax to spring controller without form?

我正在从桌面上传一张图片,然后将这张图片转换成 javascript 中的基本代码。之后,我想通过多部分请求将此图像基本代码发送到 spring 控制器。但是我没有使用表格。

HTML

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

JAVA 脚本

 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 控制器:

@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;
    }

但是当我生成 AJAX 调用时会出现 500 错误。如果我只是使用

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

然后就可以了。意思是当我使用 MultipartHttpServletRequest 地方 HttpServletRequest request 那么它是行不通的。

您正在发送它 multipart/form-data 可能这就是 HttpServletRequest 无法获取您的数据的原因,从 ajax 调用中删除 contentType 选项然后 jquery 将使用默认向导。 'application/x-www-form-urlencoded; charset=UTF-8'

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

我找到了解决方案,我们可以在 javascript 中使用 formData 而无需在任何 JSP 中使用 form 来发送 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]);

控制器:

 @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;
        }

谢谢,希望对大家有所帮助。

我会这样做:

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 并且使用的内存比长的 base64 字符串少,长 base64 字符串的大小也大 ~3 倍,使用的内存多 2 倍,因为它存储在 utf16 而不是 utf8
  • 您可以使用 new Image,它是 createElement('img')
  • 的更好的排序器版本
  • 然后我也会使用 Fetch 而不是 $.ajax 因为 jQuery 愚蠢地处理 formData(需要将 processData 和 contentType 设置为 false)
  • 然后我还会将 accept="images/*" 属性添加到文件输入以过滤掉图像