一、问题发现

前段之间为了尝鲜,小编将SpringBoot升级到2.3.3版本,体验了优雅停机的功能,感觉那是非常的舒服,当然项目升级遇到的问题也不少,比如新版本中去掉了部分依赖,需要自己手动引入等等…

然而最近在上传文件时,发现自己的项目MultipartFile取不到值,这种问题根据不同的环境出现原因也不同,ex:

  1. 前后端参数名对应不一致
  2. spring.servlet.multipart.enabled=false即关闭文件上传支持
  3. 配置文件中指定了文件上传时的大小值问题
  4. 切换内嵌容器tomcatundertow的配置问题
  5. spring.servlet.multipart.location=/tmp指定了临时文件站,但路径不存在
  6. 多次读取HttpServletRequest
  7. springboot已经有CommonsMultipartResolver,需要排除原有的Multipart配置@EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class})

小编之前配置过多次读取流来解决流只能读一次的问题,如下:

package com.zhengqing.utils;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StreamUtils;

@Slf4j
public class MyMultiReadHttpServletRequest extends HttpServletRequestWrapper {

    /**
     * 用于将流保存下来
     */
    private final byte[] body;

    public MyMultiReadHttpServletRequest(HttpServletRequest request) throws IOException {
        super(request);
        body = StreamUtils.copyToByteArray(request.getInputStream());
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream() {
            @Override
            public int read() throws IOException {
                return bais.read();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {}
        };
    }

}

之后小编将springboot版本切换到2.2.0之前的版本发现可以正常在controller层的方法参数中读到MultipartFile值,但之后的版本始终拿不到值,具体原因目前暂时未知!!!估计是版本升级后某些配置问题~

二、问题解决

虽然具体原因未知,但是可以用一种曲线救国的方式拿到前端传过来的MultipartFile参数值,如下:

@PostMapping("/importData")
@ApiOperation("导入数据")
public String importData(@RequestParam(value = "file", required = false) MultipartFile file,
    HttpServletRequest request) {
    MultipartResolver resolver = new CommonsMultipartResolver(request.getSession().getServletContext());
    MultipartHttpServletRequest multipartRequest = resolver.resolveMultipart(request);
    MultipartFile fileNew = multipartRequest.getFile("file");
    return stCrawlerArticleInfoService.importData(fileNew);
}

上传文件时可能还会出现报错:org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: org/apache/commons/fileupload/disk/DiskFileItemFactory

需要添加如下依赖解决:

<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.4</version>
</dependency>

最终如下取到上传的文件数据:

在这里插入图片描述


今日分享语句:这世上,没有谁活得比谁容易,只是有人在呼天抢地,有人在默默努力。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐