关于ajaxFileUpload上传控件可能出现的问题

一.问题

  在前端中,使用jquery的上传插件ajaxFileUpload去上传文件。控制台发现后端接口调通并返回信息,但ajaxFileUpload插件却同时进入error和success的回调函数,且不能获取到后端返回的信息。

二.代码

  先看看前后端代码。

//前端
$.ajaxFileUpload
    (
        {
            url: 'xxx', //用于文件上传的服务器端请求地址
            type: 'post',
            validSuffixes: ["xlsx", "xls"],//允许上传的文件类型(小写)
            fileSize: 1024,//单位为MB
            secureuri: false, //一般设置为false
            fileElementId: "importrebatelist", //文件上传空间的id属性
            contentType: false,
            processData: false,
            dataType: 'json', //返回值类型 一般设置为json
            success: function (data, status)  //服务器成功响应处理函数
            {
                //
            },
            error: function (data, status) {
                //
            }
        }
    );

//后端
@ApiOperation(value = "接口", httpMethod = "POST")
@RequestMapping(value = "/importFileData", method = RequestMethod.POST)
public Result importFileData(@RequestParam("importrebatelist") MultipartFile file) {
    Result rm = new Result();
    if (file.isEmpty()) {
        rm.setMessage("未接收到文件");
        rm.setSuccess(false);
    } else {
        String importResult = "";
        if (StringUtil.isNotEmpty(importResult)) {
            rm.setSuccess(false);
            rm.setMessage(importResult);
        } else {
            rm.setSuccess(true);
            rm.setMessage("导入成功");
        }
    }
    return rm;
}

三.分析  

  执行上传操作时,后端返回正常,而前端的回调函数同时进入error和success。去查看ajaxFileUpload插件代码发现了问题。

 

 

   原来是涉及到跨域问题,在解释为何会出现跨域前,这里就要解释一下关于ajax上传的原理。

  一般来说,ajax是不能发送文件,上传文件都是使用表单提交的方式,而表单提交,就需要刷新页面,这点就不符合ajax(ajax是无刷新页面来获取和提交信息)。而ajaxFileUpload上传插件使用的原理也很简单,通过创建一个iframe页面,在这个子iframe页面进行表单提交,而后端返回的信息就显示到iframe页面中,这样主页面就不需要刷新,主页面获取iframe页面的信息就能得到返回信息。基于这个原理,ajaxFileUpload就能实现无刷新上传文件。

四.解决方案

  首先,后端的返回信息一定是要返回String,或者HttpServletResponse设置content-type为text/html。如果后端选择直接返回对象的话,在ajaxFileUpload生成的iframe页面得到的返回信息会带上html标签,如下图。根据ajaxFileUpload源码原有的处理方式,主页面就会获取不到iframe的信息,继而得不到后端返回结果,且由于报错问题,会进入error和success的回调函数。

 

   iframe去做和主页面不同源的请求时会出现跨域问题,所以需要前后端同时配合,手动将其设置为同源。

//后端接口返回
String domain = "location.hostname"; //设置domain,用于跨域
String setDomain = "<script>document.domain = " + domain + ";</script>";
return setDomain + JSON.toJSONString(rm);

//前端
document.domain = location.hostname;
$.ajaxFileUpload({
    url:'xxx',
    //...
});

5.总结

  ajaxFileUpload插件可能出现的两大问题,接口返回格式处理出错(后端需返回字符)以及跨域问题,基本就可以按照上面的方法去解决。

posted @ 2021-02-08 11:45  shine声  阅读(476)  评论(0编辑  收藏  举报