SpringBoot 多文件上传、携带参数

参考文章:

  • https://stackoverflow.com/questions/36005436/the-request-was-rejected-because-no-multipart-boundary-was-found-in-springboot
  • http://6tt.co/sUur

问题:

  • 多文件上传 携带参数获取为 null
  • Failed to parse multipart servlet request; nested exception is java.io.IOException: org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found

解决方案:

先直接上代码,等会再说问题的原因。

前端:

表单上传
<form id="upmore">
    <input type="file" name="fileList" value="请选择文件" multiple id="file1">
    <input type="file" name="fileList" value="请选择文件" multiple id="file2">
    <input type="text" name="content" value="hahahahahahaha" multiple id="content">
    <input type="button" onclick="doUpload2()" value="上传2">
</form>

<script src="../js/jquery-3.4.1.min.js"></script>
<script>
    function doUpload2() {
        let form = new FormData($("#upmore")[0])

        console.log(form.get("content"))

        var settings = {
            "url": "http://localhost/tps/scp/feedback/commit",
            "method": "POST",
            "timeout": 0,
            "headers": {
                "token": "5f1b9ff0e4b08b8a8fa3d106374864651320e976dfef314722b1a9529dfcdc828e"
            },
            "processData": false,
            "mimeType": "multipart/form-data",
            "contentType": false,
            "data": form
        };

        $.ajax(settings).done(function (response) {
            console.log(response);
        });
    }
</script>

后端:

@Configuration
public class BeanConfig {
    @Bean(name = "multipartResolver")
    public MultipartResolver multipartResolver(){
        CommonsMultipartResolver resolver = new CommonsMultipartResolver();
        resolver.setDefaultEncoding("UTF-8");
        resolver.setResolveLazily(true);//resolveLazily属性启用是为了推迟文件解析,以在在UploadAction中捕获文件大小异常
        resolver.setMaxInMemorySize(40960);
        resolver.setMaxUploadSize(50*1024*1024);//上传文件大小 50M 50*1024*1024
        return resolver;
    }
}
@PostMapping("/scp/feedback/commit")
public R commit(@RequestParam(required = false) List<MultipartFile> fileList, String content,
                HttpServletRequest request) throws FileUploadException {
    System.out.println(fileList.size() + "  " + content);
    // ......
    return null;
}

分析

接口写好之后,我通常会直接使用postman先行测试,随后再拿到前端使用。如图最基本的测试,是通过了的。

接着,我将postman生成的ajax代码拷贝了一份,直接拿到了前端使用。出乎意料之外的事情发生,居然报错了:

The request was rejected because no multipart boundary was found in springboot翻译成中文就是该请求被拒绝,因为在springboot中找不到多部分边界

随之我有测试了几次,postman中请求可以成功,但是在浏览器中接口就会报错。

通过postman生成标准接口的请求代码,这非常方便。(小技巧)

在stackoverflow的一篇文章中,我找到了解决方案,使用postman生成上传文件的ajax代码时,不需要手动填写content-type请求头,postman会自动我们决定。随后,生成的正确代码也确实测试通过了。

接着在使用FormData的方式上传文件时,会出现携带的参数在后端获取为null值的情况。最终在一位网友的博客中找到了解决方案。博客中也将原因阐述的很清楚:

产生的原因就是对于multipart/formdata的请求,SpringMVC没有提供默认解析器,导致请求无法正确的被解析。需要我们自己提供一个org.springframework.web.multipart.MultipartResolver解析器。

虽然说的是SpringMVC,但是对于SpringBoot来说同样适用。在上面的代码中,通过在Java config 中配置bean的方式注入了MultipartResolver解析器。

到此,两个问题全部被解决。

事实上,在之前的代码编写过程中,处理文件上传相关的业务,我的做法都是将文件与参数进行分开处理的,对于小文件来说,这可能是不错的做法,可以提高接口的效率。但是对于大文件来说,接口效率本就不高,将请求参数与文件一并传递,倘若接口请求失败,可以即时删除占用磁盘空间的文件,减少数据冗余。

(0)

相关推荐