【问题标题】:Spring boot MultipartFile methodsSpring Boot MultipartFile 方法
【发布时间】:2017-11-27 10:45:49
【问题描述】:

在 Spring Boot 中,我们使用 MultipartFile 将文件从客户端发送到服务器。这是一个如何使用它的示例:

@RequestMapping(value = "/upload", method = RequestMethod.POST)
@ResponseBody
public String uploadFile(@RequestParam("file") MultipartFile uploadfile) {
    System.out.println("Name: " + uploadfile.getName());
    System.out.println("");
    return "Done";
}

我知道MultipartFile 是一个接口,它使得它的所有成员(即getName)都是抽象的。我不明白的是,我应该如何使用这个接口而不自己创建一个实现?

【问题讨论】:

  • 有一个实例可以被认为是MultipartFile。如果没有实例,这段代码实际上是不可能工作的。
  • 你能不能给出代码示例,我不明白,在我看来我们使用接口只是为了描述可以被其他类实现的方法
  • 你会得到一个注入接口的实现。取决于您使用的文件上传机制。 Spring 使用大量接口将您从实际实现中抽象出来。
  • @Compass 不,它没有。文件上传通过MultipartFileResolver 处理。

标签: java spring-boot


【解决方案1】:
var factory = new DiskFileItemFactory()
var fileItem = factory.createItem(
        "file",
        MediaType.APPLICATION_OCTET_STREAM_VALUE,
        true,
        "file"
)

try {
    fileItem.outputStream.use { outputStream ->
        // Copy your data into the outputStream
    }

    var multipartFile = new CommonsMultipartFile(fileItem)
} finally {
    fileItem.delete()
}

【讨论】:

    【解决方案2】:

    Spring MVC 如何处理文件上传在 Spring 参考指南的 relevant section 中进行了说明。

    当一个请求首先到达DispatcherServlet 时,它会检测到它是一个多部分请求,并将请求处理委托给配置的MultipartResolver(这又是一个接口)。 DispatcherServlet 通过众所周知的名称multipartResolver 检测到此MultipartResolver(这是在DispatcherServlet 中硬编码的)。

    这个MultipartResolver 实例所做的是将实际的HttpServletRequest 包装到MultipartServletRequest(这是HttpServletRequest) and this wrapper knowns how to handle the incoming request and create the appropriateMultipartFile` 实现的Spring MVC 扩展。

    Spring 有 3 种风格的这个界面

    1. CommonsMultipartResolver 使用 Apache Commons FileUpload
    2. StandardServletMultipartResolver使用Servlet 3.0标准Servlet API上传文件
    3. MockMultipartFile 用于单元测试

    当使用 Spring Boot 时 handle file uploadsconfigures 默认第二个选项 StandardServletMultipartResolver

    现在,当多部分请求的复杂处理完成时,DispatcherServlet 将请求传递给选定的处理程序(即您的控制器)。 RequestMappingHandlerAdapter 检查选定的请求处理方法并将填写所有方法参数。

    最后是RequestParamMethodArgumentResolver 将实际值绑定到MultipartFile 对象。在MultipartServletRequest 上使用getFiles 方法。对于默认的 Spring Boot 配置实现(StandardMultipartHttpServletRequest),这将给出StandardMultipartFile 的实例,这是所述StandardMultipartHttpServletRequest 中的嵌入类

    能够使用MultipartFile 接口的好处是您可以更改为CommonsMultipartResolver 而无需更改您的控制器。

    【讨论】:

      【解决方案3】:

      如果你查看Spring源码,你会发现CommonsMultipartFile,它实现了getName()等方法

      当您声明要接收MultipartFile 时,您实际上并不关心它是如何在幕后实现的。你只关心文件。 Spring Framework 将决定为您提供哪种实现。

      其他有趣的实现是MockMultipartFile,可以在测试期间使用。同样,由于它实现了相同的接口,因此您无需以任何方式更改方法。

      由于它是一个接口,因此需要有人提供实现。在这种情况下,Spring 在运行时提供它。

      【讨论】:

      • 感谢您的回复,但它是如何工作的,我的意思是忘记春天,只看方法 String uploadFile(@RequestParam("file") MultipartFile uploadfile) 我得到了被覆盖的接口实例,但我不知道如何以及哪个类覆盖接口,它是如何工作的?
      • 您无需知道实现该接口的确切类即可使用该接口。 stackoverflow.com/questions/21281203/…
      • @АлмасАбдразак:我觉得你应该先阅读what an interface is,然后再继续使用 Spring。大量的 Spring 是基于接口提供的原则构建的。
      • 谢谢,可能我不明白接口是如何工作的,我知道这应该是一个新问题,但你能给我一些代码示例,说明我们如何路径对接口的引用被另一个类覆盖?
      • @АлмасАбдразак 使用 IntelliJ,Ctrl+Alt+B 是 Find Implementation(s),这是一个很好的起点。
      【解决方案4】:

      Spring 有一些实现MultipartFile 接口的类。比如有CommonsMultipartFile类:http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/multipart/commons/CommonsMultipartFile.html

      当一个多部分表单提交给您的控制器时,Spring 会解析该表单,构建一些实现 MultipartFile(可能是 CommonsMultipartFile)的类对象,并以该对象作为参数调用您的控制器方法。

      所以你不需要实现MultipartFile方法,它们已经被Spring实现了。

      【讨论】:

        猜你喜欢
        • 2016-12-24
        • 2017-09-17
        • 2016-03-14
        • 2021-05-29
        • 2018-11-21
        • 2021-12-18
        • 2023-02-14
        • 2021-11-12
        • 2018-04-10
        相关资源
        最近更新 更多