SpringBoot:MultipartResolver 文件上传、大小限制相关配置、实现原理与自定义

导读:本篇文章讲解 SpringBoot:MultipartResolver 文件上传、大小限制相关配置、实现原理与自定义,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

基于

SpringBoot 2.3.2.RELEASE
Spring-web 5.2.8.RELEASE

问题

做上传下载文件时,SpringBoot获取的文件是MultipartFile,不想把文件存到服务器再上传,就使用了下面的方式进行文件流的获取

	MultipartFile file = 来源是浏览器;
	CommonsMultipartFile cFile = (CommonsMultipartFile) file;
    DiskFileItem fileItem = (DiskFileItem) cFile.getFileItem();
    InputStream in = fileItem.getInputStream();

发生下面报错

java.lang.ClassCastException: org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile cannot be cast to org.springframework.web.multipart.commons.CommonsMultipartFile
	at com.ais.cdc.service.impl.DirFileMappingServiceImpl.store(DirFileMappingServiceImpl.java:255) ~[classes/:na]

其实改成下面也行

	MultipartFile file = 来源是浏览器;
    InputStream in = file .getInputStream();

但上面报错问题是什么呢,我查了一些资料

org.apache.commons.fileupload包的选择

org.apache.commons.fileupload.disk.DiskFileItem
首先看,这个DiskFileItem是org.apache.commons.fileupload下面的

MultipartResolver文件上传解析接口

这个是一个接口,用于文件上传解析,从Spring3.1开始有两个实现

CommonsMultipartResolver:Apache Commons文件上传
在这里插入图片描述

StandardServletMultipartResolver:基于Servlet 3.0的多部分解析
在这里插入图片描述

spring.servlet.multipart 相关配置

这些配置后,是给StandardServletMultipartResolver用的,如果自定义了CommonsMultipartResolver,这些配置就会“失效”,或者说“不生效”,为什么呢,还是因为SpringBoot自动装配的默认选择问题,看下一节

spring.servlet.multipart.enabled=true
# 总上传数据大小
spring.servlet.multipart.max-request-size=1GB
# 单文件大小
spring.servlet.multipart.max-file-size=1GB
# 文件达到多少磁盘写入
spring.servlet.multipart.file-size-threshold=100MB
# 直接存服务器的路径
spring.servlet.multipart.location=/home

SpringBoot对multipartResolver的自动装配: MultipartAutoConfiguration

直接贴代码,看下面,说几点:

1.multipartResolver的默认实现StandardServletMultipartResolver:

@Bean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)这个bean的名字,就是multipartResolver,是生成的StandardServletMultipartResolver,

2.CommonsMultipartResolver是默认不生成的

@ConditionalOnMissingBean({ MultipartConfigElement.class, CommonsMultipartResolver.class }),默认没CommonsMultipartResolver的bean才创建配置

3.spring.servlet.multipart是给StandardServletMultipartResolver用的

所以如果我就要用CommonsMultipartResolver生成bean,spring.servlet.multipart白配

/**
 * {@link EnableAutoConfiguration Auto-configuration} for multi-part uploads. Adds a
 * {@link StandardServletMultipartResolver} if none is present, and adds a
 * {@link javax.servlet.MultipartConfigElement multipartConfigElement} if none is
 * otherwise defined. The {@link ServletWebServerApplicationContext} will associate the
 * {@link MultipartConfigElement} bean to any {@link Servlet} beans.
 * <p>
 * The {@link javax.servlet.MultipartConfigElement} is a Servlet API that's used to
 * configure how the server handles file uploads.
 */
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Servlet.class, StandardServletMultipartResolver.class, MultipartConfigElement.class })
//"spring.servlet.multipart"配置的开启
@ConditionalOnProperty(prefix = "spring.servlet.multipart", name = "enabled", matchIfMissing = true)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(MultipartProperties.class)
public class MultipartAutoConfiguration {

	private final MultipartProperties multipartProperties;

	//"spring.servlet.multipart"配置的引入
	public MultipartAutoConfiguration(MultipartProperties multipartProperties) {
		this.multipartProperties = multipartProperties;
	}

	//没CommonsMultipartResolver才使用"spring.servlet.multipart"配置
	@Bean
	@ConditionalOnMissingBean({ MultipartConfigElement.class, CommonsMultipartResolver.class })
	public MultipartConfigElement multipartConfigElement() {
		return this.multipartProperties.createMultipartConfig();
	}

	//默认生成StandardServletMultipartResolver 
	@Bean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
	@ConditionalOnMissingBean(MultipartResolver.class)
	public StandardServletMultipartResolver multipartResolver() {
		StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver();
		multipartResolver.setResolveLazily(this.multipartProperties.isResolveLazily());
		return multipartResolver;
	}

}

自定义multipartResolver

如果不改spring.servlet.multipart前缀,SpringBoot还是会检查报错的,所以改一下

my:
	servlet:
		multipart:
			maxUploadSize: 1073741824
			maxInMemorySize: 104857600
@Data
@Configuration
@ConfigurationProperties(prefix = "my.servlet.multipart", ignoreUnknownFields = false)
public class MultipartAutoConfiguration {

    private long maxUploadSize;

    private int maxInMemorySize;

    @Bean(name = "multipartResolver")
    public CommonsMultipartResolver getCommonsMultipartResolver() {
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
        multipartResolver.setMaxUploadSize(this.maxUploadSize);
        multipartResolver.setMaxInMemorySize(this.maxInMemorySize);
        return multipartResolver;
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/93685.html

(0)
小半的头像小半

相关推荐

半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!