1. Overzicht
In deze zelfstudie bespreken we hoe u bestanden kunt uploaden en ophalen met MongoDB en Spring Boot.
We gebruiken MongoDB BSON voor kleine bestanden en GridFS voor de grotere.
2. Maven-configuratie
Eerst voegen we de spring-boot-starter-data-mongodb afhankelijkheid van onze pom.xml :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
Daarnaast hebben we het spring-boot-starter-web . nodig en spring-boot-starter-thymeleaf afhankelijkheden om de gebruikersinterface van onze applicatie weer te geven. Deze afhankelijkheden worden ook getoond in onze Gids voor Spring Boot met Thymeleaf.
In deze tutorial gebruiken we Spring Boot versie 2.x.
3. Spring Boot-eigenschappen
Vervolgens configureren we de benodigde Spring Boot-eigenschappen.
Laten we beginnen met de MongoDB-eigenschappen :
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=springboot-mongo
We zullen ook de Servlet Multipart-eigenschappen instellen om het uploaden van grote bestanden toe te staan:
spring.servlet.multipart.max-file-size=256MB
spring.servlet.multipart.max-request-size=256MB
spring.servlet.multipart.enabled=true
4. Kleine bestanden uploaden
Nu bespreken we hoe u kleine bestanden (grootte <16 MB) kunt uploaden en ophalen met MongoDB BSON .
Hier hebben we een eenvoudig Document klas — Foto. We slaan ons afbeeldingsbestand op in een BSON Binair :
@Document(collection = "photos")
public class Photo {
@Id
private String id;
private String title;
private Binary image;
}
En we hebben een eenvoudige PhotoRepository :
public interface PhotoRepository extends MongoRepository<Photo, String> { }
Nu, voor de PhotoService , hebben we maar twee methoden:
- addPhoto() — om een Foto te uploaden naar MongoDB
- getPhoto() — om een Foto op te halen met een gegeven 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. Grote bestanden uploaden
Nu gebruiken we GridFS om grote bestanden te uploaden en op te halen.
Eerst definiëren we een eenvoudige DTO - Video – om een groot bestand weer te geven:
public class Video {
private String title;
private InputStream stream;
}
Gelijk aan de PhotoService , we hebben een VideoService met twee methoden — addVideo() en 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;
}
}
Voor meer details over het gebruik van GridFS met Spring, bekijk ons GridFS in Spring Data MongoDB-artikel.
6. Controllers
Laten we nu eens kijken naar de controllers — PhotoController en VideoController .
6.1. PhotoController
Ten eerste, we hebben de PhotoController, die gebruikmaakt van onze PhotoService om foto's toe te voegen/te krijgen .
We definiëren de addPhoto() methode om een nieuwe Foto te uploaden en te maken :
@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;
}
We hebben ook getPhoto() om een foto met een bepaalde id op te halen:
@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";
}
Houd er rekening mee dat de afbeeldingsgegevens worden geretourneerd als een byte[] , zullen we het converteren naar een Base64 String om het op de front-end weer te geven.
6.2. VideoController
Laten we vervolgens eens kijken naar onze VideoController .
Dit heeft een vergelijkbare methode, addVideo() , om een Video te uploaden naar onze 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;
}
En hier hebben we getVideo() om een Video op te halen met een gegeven 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";
}
We kunnen ook een streamVideo() . toevoegen methode die een streaming-URL maakt van de 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
Laten we tot slot onze front-end eens bekijken.
Laten we beginnen met uploadPhoto.html , die een eenvoudig formulier biedt om een afbeelding te uploaden:
<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>
Vervolgens voegen we de photos.html . toe bekijken om onze foto's weer te geven:
<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>
Evenzo hebben we de uploadVideo.html om een Video te uploaden :
<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>
En videos.html om video's weer te geven:
<html>
<body>
<h1>View Video</h1>
Title: <span th:text="${title}">title</span>
<video width="400" controls>
<source th:src="${url}" />
</video>
</body>
</html>