springmvc/springboot 上传文件(Servlet3.0支持)

Controller代码
/**
     * 文件上传
     * @param
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/uploadMiltiFile",consumes = "multipart/form-data", method = RequestMethod.POST)
    public String instantUploadMiltiFile(HttpServletRequest request, String account) {
        MultipartHttpServletRequest muti = (MultipartHttpServletRequest) request;
        MultiValueMap map = muti.getMultiFileMap();
        for (Map.Entry> entry : map.entrySet()) {
            List list = entry.getValue();
            for (MultipartFile multipartFile : list) {
                try {
                    read(multipartFile.getInputStream());
                } catch (Exception ex) {

                }
            }
        }
        return "上传文件";
    }
MultipartFile的getInputStream()方法可以获取InputStream。接下去read函数就可以处理了

这里有个奇怪的地方就是  MultipartHttpServletRequest muti = (MultipartHttpServletRequest) request;为什么request可以转型成MultipartHttpServletRequest,我们看看请求在到达Controller做了什么。springmvc/springboot 上传文件(Servlet3.0支持)_第1张图片

实际上在请求到达DispatcherServlet通过进行了请求的转型。主要进行了两个步骤,一个是判断请求是上传文件类型,另外一个是对请求进行转型。关键函数是checkMultipart。

protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
        if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
            if (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null) {
                this.logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, this typically results from an additional MultipartFilter in web.xml");
            } else if (this.hasMultipartException(request)) {
                this.logger.debug("Multipart resolution failed for current request before - skipping re-resolution for undisturbed error rendering");
            } else {
                try {
                    return this.multipartResolver.resolveMultipart(request);
                } catch (MultipartException var3) {
                    if (request.getAttribute("javax.servlet.error.exception") == null) {
                        throw var3;
                    }
                }

                this.logger.debug("Multipart resolution failed for error dispatch", var3);
            }
        }

        return request;
    }

实际上调用了multipartResolver的isMultipart方法。multipartResolver是接口,它默认标准实现是StandardServletMultipartResolver那我们看下StandardServletMultipartResolver.isMultipart方法

public boolean isMultipart(HttpServletRequest request) {
        if (!"post".equalsIgnoreCase(request.getMethod())) {
            return false;
        } else {
            String contentType = request.getContentType();
            return StringUtils.startsWithIgnoreCase(contentType, "multipart/");
        }
    }

转换的逻辑是return this.multipartResolver.resolveMultipart(request);实际上也是调用StandardServletMultipartResolver.resolveMultipart方法。我们看下方法的源码

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

调了StandardMultipartHttpServletRequest的构造

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

    }

    private void parseRequest(HttpServletRequest request) {
        try {
            Collection parts = request.getParts();
            this.multipartParameterNames = new LinkedHashSet(parts.size());
            MultiValueMap 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);
        }

    }

这里还有一个疑问就是 Collection parts = request.getParts();

实际上在Servlet3.0支持request.getParts()获取上传文件 

 

 

 

你可能感兴趣的:(工作中的学习)