MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Carregar e recuperar arquivos usando MongoDB e Spring Boot

1. Visão geral


Neste tutorial, discutiremos como fazer upload e recuperar arquivos usando MongoDB e Spring Boot.

Usaremos o MongoDB BSON para arquivos pequenos e GridFS para os maiores.

2. Configuração do Maven


Primeiro, adicionaremos o spring-boot-starter-data-mongodb dependência ao nosso pom.xml :
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

Além disso, precisaremos do spring-boot-starter-web e spring-boot-starter-thymeleaf dependências para exibir a interface do usuário do nosso aplicativo. Essas dependências também são mostradas em nosso Guia para Spring Boot com Thymeleaf.

Neste tutorial, estamos usando o Spring Boot versão 2.x.

3. Propriedades de inicialização do Spring


Em seguida, configuraremos as propriedades necessárias do Spring Boot.

Vamos começar com as propriedades do MongoDB :
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=springboot-mongo

Também definiremos as propriedades Servlet Multipart para permitir o upload de arquivos grandes:
spring.servlet.multipart.max-file-size=256MB
spring.servlet.multipart.max-request-size=256MB
spring.servlet.multipart.enabled=true

4. Fazendo upload de arquivos pequenos


Agora, discutiremos como fazer upload e recuperar arquivos pequenos (tamanho <16 MB) usando o MongoDB BSON .

Aqui, temos um Documento simples turma — Foto. Vamos armazenar nosso arquivo de imagem em um BSON Binário :
@Document(collection = "photos")
public class Photo {
    @Id
    private String id;
    
    private String title;
        
    private Binary image;
}

E teremos um PhotoRepository simples :
public interface PhotoRepository extends MongoRepository<Photo, String> { }

Agora, para o PhotoService , teremos apenas dois métodos:
  • adicionarFoto() — para carregar uma Foto para MongoDB
  • getFoto() — para recuperar uma Foto com um determinado ID
@Service
public class PhotoService {

    @Autowired
    private PhotoRepository photoRepo;

    public String addPhoto(String title, MultipartFile file) throws IOException { 
        Photo photo = new Photo(title); 
        photo.setImage(
          new Binary(BsonBinarySubType.BINARY, file.getBytes())); 
        photo = photoRepo.insert(photo); return photo.getId(); 
    }

    public Photo getPhoto(String id) { 
        return photoRepo.findById(id).get(); 
    }
}

5. Fazendo upload de arquivos grandes


Agora, usaremos o GridFS para fazer upload e recuperar arquivos grandes.

Primeiro, vamos definir um DTO simples – Vídeo – para representar um arquivo grande:
public class Video {
    private String title;
    private InputStream stream;
}

Semelhante ao PhotoService , teremos um VideoService com dois métodos — addVideo() e getVideo() :
@Service
public class VideoService {

    @Autowired
    private GridFsTemplate gridFsTemplate;

    @Autowired
    private GridFsOperations operations;

    public String addVideo(String title, MultipartFile file) throws IOException { 
        DBObject metaData = new BasicDBObject(); 
        metaData.put("type", "video"); 
        metaData.put("title", title); 
        ObjectId id = gridFsTemplate.store(
          file.getInputStream(), file.getName(), file.getContentType(), metaData); 
        return id.toString(); 
    }

    public Video getVideo(String id) throws IllegalStateException, IOException { 
        GridFSFile file = gridFsTemplate.findOne(new Query(Criteria.where("_id").is(id))); 
        Video video = new Video(); 
        video.setTitle(file.getMetadata().get("title").toString()); 
        video.setStream(operations.getResource(file).getInputStream());
        return video; 
    }
}

Para obter mais detalhes sobre como usar o GridFS com Spring, confira nosso artigo GridFS no Spring Data MongoDB.

6. Controladores


Agora, vamos dar uma olhada nos controladores — PhotoController e VideoController .

6.1. PhotoController


Primeiro, temos o PhotoController, que usará nosso PhotoService para adicionar/obter fotos .

Vamos definir o addPhoto() método para fazer upload e criar uma nova Foto :
@PostMapping("/photos/add")
public String addPhoto(@RequestParam("title") String title, 
  @RequestParam("image") MultipartFile image, Model model) 
  throws IOException {
    String id = photoService.addPhoto(title, image);
    return "redirect:/photos/" + id;
}

Também temos getPhoto() para recuperar uma foto com um determinado id:
@GetMapping("/photos/{id}")
public String getPhoto(@PathVariable String id, Model model) {
    Photo photo = photoService.getPhoto(id);
    model.addAttribute("title", photo.getTitle());
    model.addAttribute("image", 
      Base64.getEncoder().encodeToString(photo.getImage().getData()));
    return "photos";
}

Observe que, como temos os dados da imagem retornados como byte[] , vamos convertê-lo em um Base64 Sequência para exibi-lo no front-end.

6.2. Controlador de vídeo


Em seguida, vamos dar uma olhada no nosso VideoController .

Isso terá um método semelhante, addVideo() , para enviar um Vídeo para o nosso MongoDB:
@PostMapping("/videos/add")
public String addVideo(@RequestParam("title") String title, 
  @RequestParam("file") MultipartFile file, Model model) throws IOException {
    String id = videoService.addVideo(title, file);
    return "redirect:/videos/" + id;
}

E aqui temos getVideo() para recuperar um Vídeo com um determinado id :
@GetMapping("/videos/{id}")
public String getVideo(@PathVariable String id, Model model) throws Exception {
    Video video = videoService.getVideo(id);
    model.addAttribute("title", video.getTitle());
    model.addAttribute("url", "/videos/stream/" + id);
    return "videos";
}

Também podemos adicionar um streamVideo() método que criará um URL de streaming do Vídeo InputStream :
@GetMapping("/videos/stream/{id}")
public void streamVideo(@PathVariable String id, HttpServletResponse response) throws Exception {
    Video video = videoService.getVideo(id);
    FileCopyUtils.copy(video.getStream(), response.getOutputStream());        
}

7. Front-end


Finalmente, vamos ver nosso front-end.
Vamos começar com uploadPhoto.html , que fornece um formulário simples para fazer upload de uma imagem:
<html>
<body>
<h1>Upload new Photo</h1>
<form method="POST" action="/photos/add" enctype="multipart/form-data">
    Title:<input type="text" name="title" />
    Image:<input type="file" name="image" accept="image/*" />
    <input type="submit" value="Upload" />
</form>
</body>
</html>

Em seguida, adicionaremos o photos.html view para exibir nossas fotos:
<html>
<body>
    <h1>View Photo</h1>
    Title: <span th:text="${title}">name</span>
    <img alt="sample" th:src="*{'data:image/png;base64,'+image}" />
</body>
</html>

Da mesma forma, temos o uploadVideo.html para enviar um Vídeo :
<html>
<body>
<h1>Upload new Video</h1>
<form method="POST" action="/videos/add" enctype="multipart/form-data">
    Title:<input type="text" name="title" />
    Video:<input type="file" name="file" accept="video/*" />
    <input type="submit" value="Upload" />
</form>
</body>
</html>

E videos.html para exibir vídeos:
<html>
<body>
    <h1>View Video</h1>
    Title: <span th:text="${title}">title</span>
    <video width="400" controls>
        <source th:src="${url}" />
    </video>
</body>
</html>