SpringMVC 之文件上传:MultipartException 的困扰

闲话

写下这篇笔记,同时带给大家一段话,摘自某位大佬(我记不清楚是谁了哈哈哈):

最难找的 bug 往往是最低级的错误。

这段话总能让学习阶段的我排错后分析问题原因时受益匪浅。

正文

前言

个人项目开发需要完成一个文件上传删除下载的功能,这本该是简单的事情,但是却阻挠了我许久,让我的项目进度迟迟不动。当然也是因为最近事情多,但外界的事情并不是借口。。好了闲话少说,先贴一下问题

问题

问题 1:请求携带文件大小超出默认限制范围

首先是文件大小的问题,springboot 项目出现 MaxUploadSizeException 异常。springboot 默认上传文件大小限制是 1MB,默认单次请求大小限制是 10MB,超出大小就会抛出上述异常。而请求文件大小超过 1MB 和超过 10MB时的异常是不同的:

超过 1MB 时异常信息

Resolved [org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 1048576 bytes.]

超过 10MB 时异常信息

Resolved [org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (12209424) exceeds the configured maximum (10485760)]

当文件超过 10MB 时项目报错,而这一异常却无法被自定义的全局异常处理器@ControllerAdvice捕获,页面直接报 500

原因

摘录自:http://t.csdn.cn/cRQOQ

下图是 SpringMVC 的单次请求响应流程

这张图就解释了我们在 Controller 里无法捕获异常的原因。是因为 MultipartException在前两个阶段就被捕获并抛出了(并有return值),并未到达Controller层。这里也是为什么我们设置了全局捕获,可以捕获 MultipartException 异常却无法正确返回对象给前端的原因(return值被提前处理)。

解决

解决方法在摘录的大佬的文章中展示了两种,我用了最简洁方便的一种:

在工程的配置文件 application.yml 中配置请求大小限制和上传文件大小限制,以及tomcat的最大吞吐量

spring:
    servlet:
        multipart:
          max-file-size: 5MB
          max-request-size: 20MB

server:
  port: 8999
  tomcat:
    # 当文件超过tomcat的大小限制后会先于Controller触发异常,此时我们的异常处理器无法捕获异常
    max-swallow-size: 30MB # 内嵌tomcat的最大吞吐量,设置 -1 不限制

问题2:上传文件接口和请求未遵循必须条件

第二个问题出现在上传文件的前后端接口联调,下面是异常信息:

org.springframework.web.multipart.MultipartException: The current request is not a multipart request
原因

最可能犯的错误的原因和解决方法我学习总结有以下几点

1. 请求方式必须为 post

2. 请求的contentType 必须设置为以 "multipart/" 开头

3. 后端接口的接收参数需要用 @RequestParam 指定表单的key,用于接收文件数据

解决

要点如下

前端代码:

 注意这第三张图!!

后端接口

@RestController
@RequestMapping("/file")
@Slf4j
public class FileWorkerController {


    @PostMapping("upload")
    @ResponseBody
    ResultVO<String> uploadAndSaveForImage(@RequestParam("file") MultipartFile file) {
        log.info("multipart ==> {}", file);
        return ResultVO.ok();
    }
}

 学习自大佬文章:http://t.csdn.cn/LYbHF

在此表示晚辈的万分感激!

个人问题

那么我的弱智问题是在哪里呢?实际上就是在前端代码中,我封装了FormData对象,传递的却是文件file。。。无语。。

后话

所以说细节决定成败,最难找的 bug 或许出现在最低级的操作中。当你发现查遍所有资料和主要问题都没有解决时,就该找找自己的问题了。当然也可以自一开始就先注意看看是不是自己的问题。在这里我也借此警醒自己,保持谦卑,砥砺前行!!

如果有其他意见和看法,欢迎各位评论区留言!如果有其他合作或者交流的意向,也欢迎私信我!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
SpringMVC中,表单的处理是非常常见的操作。而SpringMVC提供了form:标签库来简化表单的处理,使得表单的处理更加方便和简单。 使用form:标签库,需要在JSP页面中引入form标签库的命名空间,如下所示: ``` <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> ``` 引入命名空间后,就可以使用form标签库提供的标签来处理表单了。比如,使用form:form标签创建一个表单,如下所示: ``` <form:form modelAttribute="user" method="post" action="/user/save"> <table> <tr> <td><form:label path="username">Username:</form:label></td> <td><form:input path="username" /></td> </tr> <tr> <td><form:label path="password">Password:</form:label></td> <td><form:password path="password" /></td> </tr> <tr> <td colspan="2"><input type="submit" value="Submit" /></td> </tr> </table> </form:form> ``` 在上面的代码中,form:form标签用来创建一个表单,其中modelAttribute属性用来指定表单数据绑定到的对象,method属性用来指定表单提交时使用的HTTP方法,action属性用来指定表单提交的URL。form:label标签用来创建一个标签,path属性用来指定标签绑定到的对象属性,form:input标签用来创建一个文本框,path属性用来指定文本框绑定到的对象属性,form:password标签用来创建一个密码框,path属性用来指定密码框绑定到的对象属性。 使用form:标签库可以非常方便地处理表单,提高开发效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值