【问题标题】:How do you save files for entity in Spring Data Rest?如何在 Spring Data Rest 中为实体保存文件?
【发布时间】:2020-04-22 10:30:42
【问题描述】:

在 SDR 的常规实体中,它会处理实体的所有属性,以便您将其保存到数据库中。但是你如何处理文件呢?

@Entity
public class User {
 String name;
 Set<File> myfiles; //how can I make this work? 
}

@RepositoryRestResource
public interface UserRepository extends JpaRepository<User, Long> {}

我怎样才能让用户拥有一个文件列表,可以上传和下载它们?

【问题讨论】:

    标签: spring spring-boot jpa spring-data-rest


    【解决方案1】:

    我建议你可以改用@Lob 来保存文件数据(fileData 变量如下)

    @Entity
    public class File {
        @Id
        @GeneratedValue(generator = "uuid")
        @GenericGenerator(name = "uuid", strategy = "uuid2")
        private String id;
    
        private String fileName;
    
        private String fileType;
    
        @Lob
        private byte[] fileData;
    }
    

    【讨论】:

      【解决方案2】:

      这对于 Spring Data/REST 来说是不可能的,因为它专注于结构化数据;即表和关联,在大多数情况下。

      @Lob 是有问题的,因为它迫使您将内容存储在数据库中,而数据库不一定是您想要存储它的位置。例如,文件系统或 S3 可能会更好。

      byte[] 如果你有非常大的文件也会有问题,因为你可能会导致 OutOfMemoryExceptions。

      取而代之的是一个名为Spring Content 的社区项目,可以准确解决您要解决的问题。

      Spring Content 为非结构化数据提供与 Spring Data/REST 相同的编程范式;即图像、文档、电影等。因此,使用这个项目,您可以将一个,或者在您的情况下,许多“内容”对象与您的 Spring Data 实体相关联,并通过 HTTP 管理它们,就像您对 Spring Data 实体所做的一样。

      添加到您的项目非常简单,如下所示:

      pom.xml(也可以使用启动器)

         <!-- Java API -->
         <dependency>
            <groupId>com.github.paulcwarren</groupId>
            <artifactId>spring-content-fs</artifactId>
            <version>1.0.0.M4</version>
         </dependency>
         <!-- REST API -->
         <dependency>
            <groupId>com.github.paulcwarren</groupId>
            <artifactId>spring-content-rest</artifactId>
            <version>1.0.0.M4</version>
         </dependency>
      

      配置

      @Configuration
      @EnableFilesystemStores
      @Import("org.springframework.content.rest.config.RestConfiguration.class")
      public class ContentConfig {
      
         @Bean
         FileSystemResourceLoader fileSystemResourceLoader() throws IOException {
          return new FileSystemResourceLoader(new File("/path/to/uploaded/files").getAbsolutePath());
         }
      }    
      

      要关联内容,请按如下方式修改您的用户实体:

      @Entity
      public class User {
       String name;
       List<Image> images; 
      }
      

      添加图片实体:

      @Entity
      public class Image {
      
        @ContentId
        private String contentId;
      
        @ContentLength
        private long contentLength = 0L;
      
        @MimeType
        private String mimeType = "text/plain";
      }
      

      并为此添加一个“存储”(相当于存储库,但用于内容):

      ImageStore.java

      @StoreRestResource
      public interface ImageStore extends FilesystemContentStore<Image, String> {}
      

      这就是创建 REST 端点@/users/{userId}/images 所需的全部内容。当您的应用程序启动时,Spring Content 将查看您的依赖项,查看 Spring Content Filesystem,查看您的 ImageStore 接口并注入该接口的基于文件系统的实现。它还将查看 Spring Content REST 依赖项并注入一个 @Controller 实现,该实现将 HTTP 请求转发到您的 ImageStore。就像 Spring Data 为您的 UserRepository 所做的那样。这使您不必自己实施任何这些,我认为这就是您所追求的。

      所以...

      使用注入的 REST API 管理内容:

      curl -X POST /users/{userId}/images -F 文件=@/path/to/image.jpg

      将图像存储在文件系统中的``将其与ID为userId的用户实体相关联。

      curl /users/{userId}/images/{contentId} -H "Accept: image/jpeg"

      将再次获取它等等...支持所有 CRUD 方法和视频流以及顺便说一句!

      有一些入门指南here。 Spring Content Filesystem 的参考指南是here。还有一个教程视频here。编码位从大约 1/2 处开始。

      另外几点: - 如果您使用 Spring Boot Starters,那么大部分情况下您不需要 @Configuration。
      - 就像 Spring Data 是一种抽象一样,Spring Content 也是如此,因此您不仅限于将图像存储在文件系统上。您可以将它们作为 BLOB 存储在数据库中,或者存储在像 S3 这样的云存储中。

      HTH

      【讨论】:

        猜你喜欢
        • 2019-09-30
        • 1970-01-01
        • 1970-01-01
        • 2014-05-05
        • 1970-01-01
        • 2021-06-16
        • 2018-05-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多