MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Carica e recupera file utilizzando MongoDB e Spring Boot

1. Panoramica

In questo tutorial, discuteremo come caricare e recuperare file utilizzando MongoDB e Spring Boot.

Utilizzeremo MongoDB BSON per file di piccole dimensioni e GridFS per i più grandi.

2. Configurazione Maven

Per prima cosa, aggiungeremo spring-boot-starter-data-mongodb dipendenza dal nostro pom.xml :

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

Inoltre, avremo bisogno di spring-boot-starter-web e primavera-avvio-avvio-foglia di timo dipendenze per visualizzare l'interfaccia utente della nostra applicazione. Queste dipendenze sono mostrate anche nella nostra Guida allo Spring Boot con Thymeleaf.

In questo tutorial, stiamo usando Spring Boot versione 2.x.

3. Proprietà dello stivale a molla

Successivamente, configureremo le proprietà Spring Boot necessarie.

Iniziamo con le proprietà MongoDB :

spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=springboot-mongo

Imposteremo anche le proprietà multiparte servlet per consentire il caricamento di file di grandi dimensioni:

spring.servlet.multipart.max-file-size=256MB
spring.servlet.multipart.max-request-size=256MB
spring.servlet.multipart.enabled=true

4. Caricamento di file di piccole dimensioni

Ora discuteremo come caricare e recuperare file di piccole dimensioni (dimensioni <16 MB) utilizzando MongoDB BSON .

Qui abbiamo un semplice Documento classe — Foto. Memorizzeremo il nostro file immagine in un BSON Binario :

@Document(collection = "photos")
public class Photo {
    @Id
    private String id;
    
    private String title;
        
    private Binary image;
}

E avremo un semplice PhotoRepository :

public interface PhotoRepository extends MongoRepository<Photo, String> { }

Ora, per il PhotoService , avremo solo due metodi:

  • aggiungiFoto() — per caricare una Foto a MongoDB
  • getPhoto() — per recuperare una Foto con un determinato 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. Caricamento di file di grandi dimensioni

Ora useremo GridFS per caricare e recuperare file di grandi dimensioni.

Per prima cosa, definiremo un semplice DTO:Video – per rappresentare un file di grandi dimensioni:

public class Video {
    private String title;
    private InputStream stream;
}

Simile a PhotoService , avremo un VideoService con due metodi: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; 
    }
}

Per maggiori dettagli sull'utilizzo di GridFS con Spring, controlla il nostro articolo GridFS in Spring Data MongoDB.

6. Controllori

Ora, diamo un'occhiata ai controller:PhotoController e VideoController .

6.1. Controller foto

Innanzitutto, abbiamo il PhotoController, che utilizzerà il nostro PhotoService per aggiungere/ottenere foto .

Definiremo il addPhoto() metodo per caricare e creare una nuova 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;
}

Abbiamo anche getPhoto() per recuperare una foto con un determinato 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";
}

Nota che abbiamo i dati dell'immagine restituiti come byte[] , lo convertiremo in un Base64 Stringa per visualizzarlo sul front-end.

6.2. Controller video

Quindi, diamo un'occhiata al nostro VideoController .

Questo avrà un metodo simile, addVideo() , per caricare un Video al nostro 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 qui abbiamo getVideo() per recuperare un Video con un dato 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";
}

Possiamo anche aggiungere un streamVideo() metodo che creerà un URL di streaming dal Video 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

Infine, vediamo il nostro front-end.
Iniziamo con uploadPhoto.html , che fornisce un semplice modulo per caricare un'immagine:

<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>

Successivamente, aggiungeremo il photos.html visualizza per visualizzare le nostre foto:

<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>

Allo stesso modo, abbiamo il uploadVideo.html per caricare un Video :

<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 per visualizzare i video:

<html>
<body>
    <h1>View Video</h1>
    Title: <span th:text="${title}">title</span>
    <video width="400" controls>
        <source th:src="${url}" />
    </video>
</body>
</html>