源代码分析

springboot 处理multipart/form-data 时,会将文件流缓存

    public MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException {
        return new StandardMultipartHttpServletRequest(request, this.resolveLazily);
    }




    public StandardMultipartHttpServletRequest(HttpServletRequest request, boolean lazyParsing) throws MultipartException {
        super(request);
        if (!lazyParsing) {
            this.parseRequest(request);
        }

    }



 private void parseRequest(HttpServletRequest request) {
        try {
            Collection<Part> parts = request.getParts();
            this.multipartParameterNames = new LinkedHashSet(parts.size());
            MultiValueMap<String, MultipartFile> files = new LinkedMultiValueMap(parts.size());
            Iterator var4 = parts.iterator();

            while(var4.hasNext()) {
                Part part = (Part)var4.next();
                String headerValue = part.getHeader("Content-Disposition");
                ContentDisposition disposition = ContentDisposition.parse(headerValue);
                String filename = disposition.getFilename();
                if (filename != null) {
                    if (filename.startsWith("=?") && filename.endsWith("?=")) {
                        filename = StandardMultipartHttpServletRequest.MimeDelegate.decode(filename);
                    }

                    files.add(part.getName(), new StandardMultipartHttpServletRequest.StandardMultipartFile(part, filename));
                } else {
                    this.multipartParameterNames.add(part.getName());
                }
            }

            this.setMultipartFiles(files);
        } catch (Throwable var9) {
            this.handleParseFailure(var9);
        }

    }


其中 request.getParts()  会将前端文件流缓存到本地临时文件夹,当我们作为流使用时,请求相当于读取本地临时文件,这样请求传入会消耗大量的时间,处理造成了两倍的时间开销

个人处理方法

1、application.yml中配置,其中 resolveLazily为懒加载,对应StandardMultipartHttpServletRequest 中resolveLazily,构造方法时controller入参如果没有form-data相关参数是不会调用 parseRequest方法

spring:
  servlet:
    multipart:
      resolve-lazily: true  

2、controller代码段

   @PostMapping(value = "/test", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public String test(HttpServletRequest request) throws IOException, InterruptedException, ServletException {
        ServletFileUpload upload = new ServletFileUpload();
        upload.setHeaderEncoding(request.getCharacterEncoding());
        if (ServletFileUpload.isMultipartContent(request)) {
            InputStream inputStream;
            long contentLength = request.getContentLengthLong();
            FileItemIterator itemIterator = upload.getItemIterator(request);
            if (itemIterator.hasNext()) {
                FileItemStream next = itemIterator.next();
                FileItemHeaders headers = next.getHeaders();
                inputStream = next.openStream();
            } else {
                //当没有配置懒加载时调用
                Part file = request.getPart("file");
                inputStream = file.getInputStream();
            }
            // inputStream 处理逻辑
            testService.run(inputStream, contentLength);
        }
        return "success";
    }

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐