如何在requestBody中将MultipartFile传递给Spring Boot Rest Controller

时间:2019-04-20 14:11:29

标签: spring spring-boot

因此,我看到了在MultiPartFile中而不是@RequestParam中传递@RequestBody类型的示例。这似乎是人们建议使用@RestController这样的文件内容的一种非常常见的方式

public ResponseEntity<String> submitFile(@RequestParam(value="file") MultipartFile file)

我想知道如何通过URL传递文件数据是一种好习惯。为什么不通过@RequestBody传递它呢?

所以我将上面的代码更改为这样的

public ResponseEntity<String> submitFile(@RequestBody MyCustomObj myObj)

myCustomObj是一种pojo,只有一个名为MultipartFile类型的文件的字段

问题是我只有招摇和邮递员来测试它,并且当我使用@RequestBody方法时,没有一个像在传递{{1 }}在MultipartFile中。

有人可以进一步说明这一点,并告诉我正确的方法吗?

2 个答案:

答案 0 :(得分:0)

@RequestParam映射到多部分请求中的查询参数,表单数据和零件,而不仅仅是官方文档中提到的查询参数。 https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestParam.html

不应将文件作为请求主体(以JSON序列化)发送。 相反,您应该使用内容类型“ multipart / form-data”进行文件上传(如下面的HTML 4规范所述),在这种情况下,@ RequestParam将是要使用的适当注释 https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4

答案 1 :(得分:0)

作为替代方案,根据您的评论,我建议您看一下名为Spring Content的社区项目。这提供了存储上的资源抽象,从而为您的内容的存储位置提供了灵活性,并且为您注入了服务和控制器实现,因此您无需自己实现。另外,正如您提到的那样,它很重要,Spring Content允许您也将上传的内容与Spring Data实体相关联。

将其添加到项目中将如下所示:

  

pom.xml(假设还提供Maven。也可以使用Spring Boot启动器)

    <!-- Java API -->
    <!-- just change this depdendency if you want to store somewhere else -->
    <dependency>
        <groupId>com.github.paulcwarren</groupId>
        <artifactId>spring-content-fs</artifactId>
        <version>0.8.0</version>
    </dependency>
    <!-- REST API -->
    <dependency>
        <groupId>com.github.paulcwarren</groupId>
        <artifactId>spring-content-rest</artifactId>
        <version>0.8.0</version>
    </dependency>
  

StoreConfig.java

@Configuration
@EnableFilesystemStores
@Import(RestConfiguration.class)
public class StoreConfig {

    @Bean
    FileSystemResourceLoader fileSystemResourceLoader() throws IOException {
        return new FileSystemResourceLoader(new File("/path/to/uploaded/files").getAbsolutePath());
    }

}
  

FileStore.java

  @StoreRestResource(path="files")
  public interface FileStore extends Store<String> {
  }

就是这样。 FileStore本质上是一个通用的Spring ResourceLoader。 spring-content-fs依赖性将导致Spring Content注入基于文件系统的实现。如果spring-content-rest将HTTP请求转发到@Controller服务的方法上,则FileStore依赖性将导致Spring Content也注入一个实现。

因此,您现在在/files处可以使用基于REST的全功能(POST,PUT,GET,DELETE)文件服务,该服务将使用您的FileStore来检索(和存储){{ 1}}。

所以:

/path/to/uploaded/files

将上传curl --upload-file some-image.jpg /files/some-image.jpg并将其存储在服务器上的some-image.jpg中。

并且:

/path/to/uploaded/files

将再次检索它。

HTH

在有用的情况下,注入的控制器也支持视频流。

稍后/如果要将内容与Spring Data实体关联时,只需将FileStore扩展为curl /files/some-image.jpg而不是ContentStore,然后将其键入Spring与您关联的数据实体,并将Spring Content批注添加到您的实体,如下所示:

Store

就是这样。如您所料,REST端点会发生变化,因此您现在可以使用与Spring Data实体相同的URI空间来寻址内容。所以:

//@StoreRestResource(path="files") <-- no longer required public interface FileStore extends ContentStore<YourEntity, String> { } @Entity public class YourEntity { @Id ... @ContentId private String contentId; @ContentLength private String contentLen; @MimeType private String contentType; }

将上传curl --upload-file some-image.jpg /yourEntities/{yourEntityId},将其存储在服务器上的some-image.jpg中,并将其与实体/path/to/uploaded/files关联。

并且:

yourEntityId

将再次检索它。

可以使用常规的curl /yourEntities/{yourEntityId}@OneToOne关联多个内容,并以一种(希望的)直观的方式将其反映在URI中。

HTH