Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何将文件上传集成到SpringDataREST存储库中?_Java_Spring_Http_File Upload_Spring Data Rest - Fatal编程技术网

Java 如何将文件上传集成到SpringDataREST存储库中?

Java 如何将文件上传集成到SpringDataREST存储库中?,java,spring,http,file-upload,spring-data-rest,Java,Spring,Http,File Upload,Spring Data Rest,我想将文件上传和下载集成到SpringDataREST存储库中 @BasePathAwareController @ExposesResourceFor(Tutor.class) public class TutorRepositoryController { private AttachmentAssembler attachmentAssembler; private AttachmentRepository attachmentRepository; priva

我想将文件上传和下载集成到SpringDataREST存储库中

@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));
    }
}
我有一个
DataFile
类(参见下面的实现),它总是伴随着一些元数据。有一个
DataFileRepository
来存储元数据和文件之间关系的信息

用户应该能够上传web应用程序表单中的文件以及元数据。元数据应该存储在数据库表中,而文件被上传到某个文件存储中时,文件的路径将再次存储在实体中

我想使用SpringDataREST来实现这一点。我的方法是在
数据文件
实体中包含一个
多部分文件
,并将其标记为
@Transient
@RestResource(exported=false)
,因此它不在实体的任何表示形式中,但可以上载。 上载时,
AbstractRepositoryEventListener
会覆盖
onBeforeCreate
,并在此步骤中上载文件

但使用这种方法,我很难将该文件包含在HTTP请求主体中(数据文件的JSON表示形式)

其他方法包括实现
@RestRepositoryController
来扩充
DataFileRepository
,但前面提到的方法是我最喜欢的

使用SpringDataREST(存储库)上传文件的最佳实践是什么


我没有找到只使用SpringDataREST来实现这一点的方法,但是这个解决方案很好地集成到了存储库中,并且不需要太多的手写代码

下面是一个不同于问题的解决方案的示例,但您应该了解这个想法

基本上创建一个
@BasePathAwareController
,这样它就可以适应您可能为Spring数据REST设置的基本路径。然后使用适当的路径在控制器内创建映射。在本例中,存在一个
@PostMapping
,其中包含指向
导师
存储库的路径以及上载到此处的相关附件的子路径

您可以使用此方法进行验证,也可以在存储库的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));
    }
}
在本例中,我使用了一个方面将处理应用于存储库的
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));
    }
}

我有完全相同的问题,你找到解决方案了吗?不是一个纯粹使用SpringDataREST的解决方案,而是结合aspects的解决方案,它工作得很好,是一个与REST很好集成的解决方案。我会添加一个答案,也许其他人会给出一个更好的答案。我只是针对一个类似的问题问了一个新问题,如果你能在这里或那里添加答案(任何一个),那就太好了!!请参阅下面的我的实现。在您的回答中,文件被放入附件,然后存储库保存它。它到底去了哪里?SDR能处理吗?它是否像附件的其他属性一样写入数据库?文件将传递给附件对象。然后将其上载到方面中的服务。如果您愿意,也可以在控制器中执行此操作。我选择在任何附件创建之前在相位中这样做。您希望我将此添加到答案中吗?是的,这将非常有用,谢谢,因为我不知道如何保留已保存文件与实体本身的关系。您是否从服务中获得某种文件句柄,然后将该句柄保存在附件实体中?添加了我的方面代码。基本上是这样的:用户单击upload,然后调用
BasePathAwareController
@PostMapping
,然后将
多部分文件
存储到磁盘上的临时文件中-将
文件
添加到
附件
对象中。然后调用repository save函数。此方法已通过aspect进行了扩展,aspect获取此临时文件,将其上载到AWS S3服务,并将S3 bucket中的路径保存到
附件
对象。在aspect之后,调用正常的存储库代码(保存到数据库等)。