SpringBoot文件上传同时,接收复杂参数

这篇具有很好参考价值的文章主要介绍了SpringBoot文件上传同时,接收复杂参数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

环境信息

问题描述

错误分析

解决方法

简单参数

总结


环境信息

        Spring Boot:2.0.8.RELEASE

        Spring Boot内置的tomcat:tomcat-embed-core 8.5.37

问题描述

        收到文件上传的开发工作,要求能适配各种场景,并且各场景的请求参数不一样,因此接收的参数不能是固定的几个字段,要有类似Map的字段来接收动态参数。

        拟使用MultipartFile[] files来接收文件列表,用自定义对象UploadFileDto来接收上传参数(里面包含一个Map)

        UploadFileDto.java

@ApiModel("文件上传dto")
@Data
public class UploadFileDto {
    @ApiModelProperty("处理器,在Spring容器里的名称")
    private String handlerName;

    @ApiModelProperty("交易代码")
    private String bizCode;

    @ApiModelProperty("交易ID")
    private String bizId;

    @ApiModelProperty("上传配置名称,对应配置文件里的配置")
    private String uploadConfigName;

    @ApiModelProperty("动态信息")
    private Map<String, Object> dynamicDto;

    @ApiModelProperty("上传时间")
    private String uploadDt;

    @ApiModelProperty("限定文件大小")
    private long defaultFileSize;

    @ApiModelProperty("限定文件格式,多个用逗号隔开")
    private String defaultFileSuffix;

    @ApiModelProperty("默认路径之后的文件上级目录")
    private String parentDir;

    @ApiModelProperty("备注信息")
    private String remark;

    @ApiModelProperty("上传后的文件信息")
    private List<FileInfoDto> fileInfoDtos;

}

Controller:

@RestController
@RequestMapping("/fileCommmon")
@Api(tags = "公共-文件操作")
public class FileUpDownLoadController extends BaseController {

    @Resource
    private UpDownLoadService upDownLoadService;

    @PostMapping(value = "/upload")
    @ApiOperation("文件上传")
    public ResponseDto<UploadFileDto> uploadFile(@RequestParam("files") MultipartFile[] files, @RequestPart() UploadFileDto uploadFileDto) {
        upDownLoadService.uploadFile(uploadFileDto, files);
        return getResponseDto(uploadFileDto);
    }
}

Controller方法,使用@RequestParam("files") MultipartFile[] files来接收文件列表

使用@RequestPart() UploadFileDto uploadFileDto来接收复杂参数。

UpDownLoadService是上传实现类,这里暂时不暂时源码。

可是,在访问该接口的时候,报错了:org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/octet-stream' not supported

org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/octet-stream' not supported
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:226)
    at org.springframework.web.servlet.mvc.method.annotation.RequestPartMethodArgumentResolver.resolveArgument(RequestPartMethodArgumentResolver.java:134)
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:124)
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:131)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:891)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:981)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:884)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:858)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)

错误分析

org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/octet-stream' not supported,意思是应用不支持'application/octet-stream'这种文件类型

Swagger2里的请求参数:

SpringBoot文件上传同时,接收复杂参数

SpringBoot文件上传同时,接收复杂参数 SpringBoot文件上传同时,接收复杂参数

 分析异常堆栈,是在AbstractMessageConverterMethodArgumentResolver的readWithMessageConverters方法里抛出的:

SpringBoot文件上传同时,接收复杂参数
         分析这个方法里的代码,发现Spring在尝试使用各个消息转换器(HttpMessageConverter)来处理请求。这里的contentType值是'application/octet-stream',发现找不到可用的消息转换器:

genericConverter.canRead(targetType, contextClass, contentType) ,因此无法解析、转换消息,因此抛出了异常。

         确切的说,上面说的是处理请求参数uploadFileDto,第一个请求参数files已经在下面这个地方处理了(文件类型参数使用MultipartResolutionDelegate.resolveMultipartArgument来处理):

SpringBoot文件上传同时,接收复杂参数

注:

messageConverters的值(这个看各个应用里注册的消息转换器类型、顺序):

SpringBoot文件上传同时,接收复杂参数

经常使用的是MappingJackson2HttpMessageConverter消息转换器,这个是SpringBoot默认用来处理消息的,将原始请求转成json格式,再转成目标类型的格式,是Jackson

targetClass是UploadFileDto对应的Class

解决方法

        明白了问题产生的原因之后,就有了解决思路:增加一个消息转换器,用于支持'application/octet-stream'。

最简单的添加方式,新增一个类,继承AbstractJackson2HttpMessageConverter,这个也是上面说的MappingJackson2HttpMessageConverter的父类

@Component
public class MultipartJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter {

    /**
     * Converter for support http request with header Content-Type: multipart/form-data
     */
    public MultipartJackson2HttpMessageConverter(ObjectMapper objectMapper) {
        super(objectMapper, MediaType.APPLICATION_OCTET_STREAM);
    }

    @Override
    public boolean canWrite(Type type, Class<?> clazz, MediaType mediaType) {
        return false;
    }

    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        return false;
    }

    @Override
    protected boolean canWrite(MediaType mediaType) {
        return false;
    }
}

 加了上面的转换器之后:

SpringBoot文件上传同时,接收复杂参数

 读取之后的body类型就是UploadFileDto

SpringBoot文件上传同时,接收复杂参数

 至此,问题解决,后端程序能够正常接收、处理前端发过来的文件列表,以及复杂参数。

简单参数

如果后端程序不需要接收复杂参数,而是只需要固定的几个简单参数,那么就很简单,比如:

Controller:


    @PostMapping(value = "/upload2")
    @ApiOperation("文件上传2")
    public ResponseDto<String> uploadFile(@RequestParam("files") MultipartFile[] files,  @RequestPart() String remark) {
        System.out.println("remark = " + remark);
        upDownLoadService.uploadFile(remark, files);
        return getResponseDto(remark);
    }

此时,contentType值是'application/octet-stream'的String的参数,Spring有提供了默认的消息转换器StringHttpMessageConverter,支持所有的格式,就不需要自定义MappingJackson2HttpMessageConverter消息转换器了。

SpringBoot文件上传同时,接收复杂参数

SpringBoot文件上传同时,接收复杂参数

总结

回顾一下,如果需要复杂参数(自定义对象接收前端参数),那么需要自定义消息转换器(如AbstractJackson2HttpMessageConverter),来支持contentType值是'application/octet-stream'类型的参数,并将其转换成目标格式;

如果不需要复杂参数,只是String等类型,那么不需要自定义消息转换器;

消息转换器是SpringBoot处理前端传输的数据,并转换成接口参数的类型的转换器,转换前、转换后还支持自定义插件处理。详见AbstractMessageConverterMethodArgumentResolver的readWithMessageConverters

SpringBoot文件上传同时,接收复杂参数

@RequestParam和@RequestPart的区别,可以自行查找资料

参考:

 rest - @RequestPart with mixed multipart request, Spring MVC 3.2 - Stack Overflow

@RequestPart同时接收文件和json后端报错 - 简书 (jianshu.io)文章来源地址https://www.toymoban.com/news/detail-485615.html

到了这里,关于SpringBoot文件上传同时,接收复杂参数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Flume多路复用模式把接收数据注入kafka 的同时,将数据备份到HDFS目录

    启动hadoop、在hdfs中创建需要访问的目录 配置Hadoop的核心配置文件 core-site.xml :设置Hadoop的核心配置参数,例如NameNode的地址、数据块大小、副本数量等。示例配置如下: hdfs-site.xml :设置HDFS(Hadoop分布式文件系统)的参数,例如数据块复制因子、NameNode的存储路径等。示例配

    2024年02月16日
    浏览(45)
  • axios同一个接口,同时接收 文件 或者 数据

    1、前端代码  主要是: if (response.data instanceof Blob)  判断是否是 Blob 对象, 否则使用: response.data = JSON.parse(await (response.data).text()) 将后台返回的内容转成 文本 返回 主要是: responseType: \\\'blob\\\' 2、后端代码 需要注意的是: response.setHeader(\\\"Access-Control-Expose-Headers\\\", \\\"filename\\\"); 否则

    2024年02月12日
    浏览(58)
  • SpringBoot接收请求参数的方式

    因为SpringBoot封装了Servlet,所以也允许使用HttpServletRequest类中的方法来获取 使用postman发送:http://localhost:8080/demo01?name=张三age=30,查看结果 springboot允许直接使用参数获取,简单优雅;另外,还也可使用“@RequestParam”注解给参数设置别名,这样页面提交的参数名使用别名也能

    2024年02月16日
    浏览(49)
  • SpringBoot - Post请求-接收参数

    1、下面样例 Controller 接收 form-data 格式的 POST 数据: 2、下面是一个简单的测试样例: 1 、如果没有传递参数   Controller   将会报错,这个同样有如下两种解决办法: 使用  required = false  标注参数是非必须的。 使用   defaultValue   给参数指定个默认值。 2、下面是一个简

    2024年02月08日
    浏览(85)
  • SpringBoot如何优雅接收前端请求参数

    @RequestParm 我们可以通过 @RequestParm 注解去绑定请求中的参数,将(查询参数或者form表单数据)绑定到controller的方法参数中,通俗点说就是,我们可以在get请求和post请求中使用改注解,get请求中会从查询参数中获取参数,post请求会从form表单或者查询参数中获取参数 默认情况

    2024年02月11日
    浏览(34)
  • springboot项目接收一个日期类型参数

            1. 在Controller的方法参数中使用 @RequestParam 注解接收日期参数,可以通过指定日期格式实现,例如:         2.使用 @PathVariable 注解接收日期参数,例如         3. 在请求体中发送JSON格式的数据,并使用 @RequestBody 注解接收日期类型的字段,例如:      

    2024年02月12日
    浏览(37)
  • 使用Postman测试文件和对象同时上传

    后端接口是需要两个参数,一个参数用来接收上传文件,另一个参数用来传递对象。后端接收文件可以采用MultipartFile来接收,对象采用json数据进行接收, 采用@RequestPart注解进行数据绑定。 采用@RequestPart注解的原因,文末附: 代码示例: 使用postman上传图片要选择form-data方式

    2024年02月14日
    浏览(39)
  • postman同时上传文件和json数据

    2024年02月11日
    浏览(32)
  • springboot接收参数的几种方式

    传参格式:?号传参,在地址栏上加参数 传参格式:请求体传参 form-data的请求是在body中,为key=value格式,同时可以传文件,Content-Type为multipart/form-data,后端可以用@RequestParam接收。 json传参也是在body当中,只不过json是一种数据格式,后端可以用@RequestBody接收。 地址栏传参,

    2024年02月10日
    浏览(60)
  • SpringBoot接口如何正确地接收时间参数

    唠嗑部分 在做Java开发时,肯定会碰到传递时间参数的情况吧,比如用户的出生日期、活动的开始,结束日期等等,这些参数往往是由前端传递过来的,那么在SpringBoot项目中,该如何正确的接收日期参数呢,这便是我们今日所说的内容 首先我们来回顾一下常用的几种传参方式

    2024年02月15日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包