一、 SpringMVC文件上传

SpringMVC对文件上传提供了良好的支持,在Springboot中仅需提供简单的配置则可以完成文件上传功能。在SpringMVC中,DispatcherServlet会通过适配器模式将HttpServletRequest转为MultipartHttpServletRequest对象。MultipartHttpServletRequest接口扩展了HttpServletRequest接口和MultipartRequest接口的所有方法,并且自定义了一些操作文件的方法,从而通过这些方法实现文件上传。

public interface MultipartHttpServletRequest extends HttpServletRequest, MultipartRequest {

	/**
	 * Return this request's method as a convenient HttpMethod instance.
	 */
	@Nullable
	HttpMethod getRequestMethod();

	/**
	 * Return this request's headers as a convenient HttpHeaders instance.
	 */
	HttpHeaders getRequestHeaders();

	/**
	 * Return the headers for the specified part of the multipart request.
	 * <p>If the underlying implementation supports access to part headers,
	 * then all headers are returned. Otherwise, e.g. for a file upload, the
	 * returned headers may expose a 'Content-Type' if available.
	 */
	@Nullable
	HttpHeaders getMultipartHeaders(String paramOrFileName);

}

HttpServletReuqest和MultipartHttpServletRequest的大致关系如图:
在这里插入图片描述


二、SpringBoot配置文件上传

在使用SpringMVC上传文件时,还需要配置MultipartHttpServletRequest,而这个任务是通过MultipartResolver接口实现。在Springboot机制中,如果你没有配置MultipartResolver对象,那么springboot会自动为你创建一个MultipartResolver对象,这个对象实际为StandardServletMultipartResolver。常用的文件配置项有一下几条:

#是否起开SpringMVC上传功能
spring.servlet.multipart.enabled=true
#指定默认上传的文件夹
spring.servlet.multipart.location=
#指定默认上传单个文件大小(默认是1MB)
spring.servlet.multipart.max-file-size=1MB
#指定所有文件总共大小(默认是10MB)
spring.servlet.multipart.max-request-size=10MB

三、SpringBoot配置文件上传常见异常

1. java.lang.IllegalStateException: Unable to process parts as no multi-part configuration has been provided

这个异常通常是因为关闭了SpringMVC文件上传功能造成的,将springboot配置改为:spring.servlet.multipart.enabled=true(开启文件上传功能)即可。

2. FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 1048576 bytes.

这个错误是最常见的,因为SpringMVC文件上传默认单个文件上传大小为1MB,也就是1048576 bytes,此时应该就是你上传的文件超过了1MB,只需要将SpringMVC支持单个文件上传大小调大即可。spring.servlet.multipart.max-file-size=?MB。

3. SizeLimitExceededException: the request was rejected because its size (xxxx) exceeds the configured maximum (xxxx)

这个错误在于单次请求文件上传文件总大小超过SpirngMVC文件上传总大小,这个总大小默认是10MB,可以通过spring.servlet.multipart.max-request-size=?MB修改。


四、SpringBoot实现文件上传功能

通过以上的简单介绍,现在让我们来实现一个SpringBoot文件上传功能,首先我配置了SpringMVC单个文件上传文件大小10MB和单次请求上传文件总大小100MB,并且开启SpringMVC文件上传功能。

spring:
  servlet:
    multipart:
    # 是否开启springMVC 多部分上传功能(默认开启)
      enabled: true
    # 上传单个文件大小(默认是1MB)
      max-file-size: 10MB
    # 限制所有文件大小
      max-request-size: 100MB

一.使用MultipartFile实现文件上传。

MultipartFile接口和MultipartHttpServletRequest接口并没有关系,但是MultipartFile接口的实现类StandardMultipartFileStandardMultipartHttpServletRequest的静态内部类,所以可以使用MultipartFile实现文件上传,具体实现可以查看StandardMultipartHttpServletRequest类源代码。使用也十分简单,代码如下:

    @RequestMapping(value = "/upload", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public void uploadFile(@RequestParam(value = "file") MultipartFile multipartFile) throws IOException {
        //获取上传文件名称
        String fileName = multipartFile.getOriginalFilename();
        //获取上传文件类型
        String contentType = multipartFile.getContentType();
        //获取上传文件输入流,便于文件内容读写操作
        InputStream inputStream = multipartFile.getInputStream();
        System.out.println("fileName = " + fileName + ", contentType = " + contentType);
    }

使用@RequestParam将参数名为file的参数转换为一个MultipartFile对象,然后就可以通过getOriginalFilename方法获取文件名称,getContentType方法获取文件类型,getInputStream方法获取一个输入流,便可以对文件进行操作。采用PostMan测试:
在这里插入图片描述
控制台输入结果:
在这里插入图片描述
对于MultipartFile实现文件上传可以参看StandardMultipartHttpServletRequest源码,这里不再过多叙述。


二.使用MultipartHttpServletRequest实现文件上传(推荐)。

在默认情况下,Spring推荐使用StandardMultipartHttpServletRequest,这个类也就是MultipartHttpServletRequest接口的实现类,文件上传处理流程主要在StandardMultipartHttpServletRequest中实现。StandardMultipartHttpServletRequest可以一次性处理多个文件上传,而且不用像MultipartFile那样需要指定参数名称。常规的使用如下:

    @RequestMapping(value = "/upload", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public void uploadFile(HttpServletRequest request) throws IOException {

        // 强制将HttpServletRequest转为MultipartHttpServletRequest
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        //获取指定MultipartFile文件
        MultipartFile file = multipartRequest.getFile("java");
        //获取文件名称
        String originalFilename = file.getOriginalFilename();
        //保存上传文件到xxx路径
        file.transferTo(Paths.get("xxx"));

        //不指定上传文件参数,而是获取整个上传文件集合
        MultiValueMap<String, MultipartFile> multiFileMap = multipartRequest.getMultiFileMap();
        //遍历整个上传文件集合,获取上传文件
        Iterator<String> MultipartFileIterator = multiFileMap.keySet().iterator();
        while (MultipartFileIterator.hasNext()) {
            String key = MultipartFileIterator.next();
            //这里是集合的原因是,可能一个参数上传多个文件。
            List<MultipartFile> multipartFiles = multiFileMap.get(key);
            System.out.println("当前上传文件参数: " + key);
            multipartFiles.forEach(multipartFile -> {
                System.out.println("上传文件名称: " + multipartFile.getOriginalFilename() + ", 上传文件类型:" + multipartFile.getContentType());
            });
            System.out.println("------------分割----------");
        }
    }

使用PostMan发送4个文件,其中两个为java,两个为docker。控制输入结果如下:
在这里插入图片描述
控制台打印结果:
在这里插入图片描述
这大概是SpringMVC最常见的两种上传文件方式,MultipartHttpServletRequest拥有更多可操作的方法,而且更方便处理多个文件同时上传。MultipartFile适合单个文件上传,两种各有自己的优势,根据自己的情况选择即可。


Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐