如何将文件上传集成到Spring Data REST存储库中?

问题描述 投票:0回答:1

我想将文件上传和下载集成到Spring Data REST存储库中。

我有一个DataFile类(请参见下面的实现),该类总是伴随着一些元数据。 DataFileRepository用于存储有关元数据和文件之间的关系的信息。

用户应该能够以网络应用程序的形式与元数据一起上传文件。当文件上传到文件存储时,元数据应存储在数据库表中,然后将文件路径再次存储在实体中。

我想使用Spring Data REST做到这一点。我的方法是在MultipartFile实体中包含DataFile并将其标记为@Transient@RestResource(exported = false),这样它就没有实体的任何表示形式,但可以上载。当上传时,AbstractRepositoryEventListener会覆盖onBeforeCreate并在此步骤中上传文件。

但是用这种方法,我努力将文件包含在HTTP请求正文中(DataFile的JSON表示。

[其他方法将包括实现@RestRepositoryController以增强DataFileRepository,但前面提到的方法将是我的最爱。

使用Spring Data REST(存储库)上传文件的最佳实践是什么?

@Data
@Entity
@Table(name = "data_files")
public class DataFile {
    @Id
    @GeneratedValue
    @Setter(AccessLevel.NONE)
    private long identifier;

    @NotBlank
    @Column(name = "path")
    @RestResource(exported = false)
    private String path;

    @Embedded
    private Metadata metadata;

    public DataFile() {
        metadata = new Metadata();
    }

    public DataFile(Metadata metadata) {
        this.metadata = metadata;
    }
}
java spring http file-upload spring-data-rest
1个回答
0
投票

我没有找到一种仅通过使用Spring Data REST来做到这一点的方法,但是该解决方案很好地集成到了存储库中,并且不需要太多的手写代码。

以下是针对与问题不同的项目的此类解决方案的示例,但您应该明白这一点。

基本上创建一个@BasePathAwareController,使其适应您可能已为Spring Data REST设置的基本路径。然后使用适当的路径在控制器内部创建映射。在这种情况下,存在一个@PostMapping,其中包含tutors存储库的路径,以及相关附件的子路径,该子路径在此处上传。

您可以使用此方法进行验证,也可以介绍存储库的save方法的一个方面。

@BasePathAwareController
@ExposesResourceFor(Tutor.class)
public class TutorRepositoryController {
    private AttachmentAssembler attachmentAssembler;

    private AttachmentRepository attachmentRepository;

    private TutorRepository tutorRepository;

    private RepositoryEntityLinks entityLinks;

    @Autowired
    public TutorRepositoryController(AttachmentAssembler attachmentAssembler,
                                     AttachmentRepository attachmentRepository,
                                     TutorRepository tutorRepository,
                                     RepositoryEntityLinks entityLinks) {
        this.attachmentAssembler  = attachmentAssembler;
        this.attachmentRepository = attachmentRepository;
        this.tutorRepository      = tutorRepository;
        this.entityLinks          = entityLinks;
    }

    @PostMapping(value = "/tutors/{id}/attachments/{name}")
    public ResponseEntity<EntityModel<Attachment>> saveAttachment(@RequestParam("data") MultipartFile file,
                                                                  @PathVariable long id,
                                                                  @PathVariable String name) {
        Tutor thisTutor = tutorRepository.findById(id);
        File tempFile;
        try {
            tempFile = File.createTempFile(FilenameUtils.getBaseName(file.getOriginalFilename()),
                                           FilenameUtils.getExtension(file.getOriginalFilename()));

            StreamUtils.copy(file.getResource().getInputStream(), new FileOutputStream(tempFile));
        } catch (IOException e) {
            throw new RuntimeException("Could not create temporary file of uploaded file.");
        }

        Attachment saved =
                    attachmentRepository.save(new Attachment(name, thisTutor, tempFile, file.getOriginalFilename()));

        return ResponseEntity.created(entityLinks.linkForItemResource(Attachment.class, saved.getIdentifier())
                                                  .toUri()).body(attachmentAssembler.toModel(saved));
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.