1. Tổng quan
Trong hướng dẫn này, chúng ta sẽ thảo luận về cách tải lên và truy xuất tệp bằng MongoDB và Spring Boot.
Chúng tôi sẽ sử dụng MongoDB BSON cho các tệp nhỏ và GridFS cho những cái lớn hơn.
2. Cấu hình Maven
Đầu tiên, chúng tôi sẽ thêm spring-boot-starter-data-mongodb sự phụ thuộc vào pom.xml của chúng tôi :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
Ngoài ra, chúng tôi sẽ cần spring-boot-starter-web và spring-boot-starter-thymeleaf phụ thuộc để hiển thị giao diện người dùng của ứng dụng của chúng tôi. Những phụ thuộc này cũng được hiển thị trong Hướng dẫn Khởi động Mùa xuân với Thymeleaf của chúng tôi.
Trong hướng dẫn này, chúng tôi đang sử dụng Spring Boot phiên bản 2.x.
3. Thuộc tính khởi động mùa xuân
Tiếp theo, chúng tôi sẽ cấu hình các thuộc tính Spring Boot cần thiết.
Hãy bắt đầu với thuộc tính MongoDB :
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=springboot-mongo
Chúng tôi cũng sẽ đặt các thuộc tính Servlet Multipart để cho phép tải lên các tệp lớn:
spring.servlet.multipart.max-file-size=256MB
spring.servlet.multipart.max-request-size=256MB
spring.servlet.multipart.enabled=true
4. Tải lên các tệp nhỏ
Bây giờ, chúng ta sẽ thảo luận về cách tải lên và truy xuất các tệp nhỏ (kích thước <16MB) bằng MongoDB BSON .
Ở đây, chúng tôi có một Tài liệu đơn giản lớp - Ảnh. Chúng tôi sẽ lưu trữ tệp hình ảnh của mình trong một BSON Nhị phân :
@Document(collection = "photos")
public class Photo {
@Id
private String id;
private String title;
private Binary image;
}
Và chúng tôi sẽ có một PhotoRepository đơn giản :
public interface PhotoRepository extends MongoRepository<Photo, String> { }
Bây giờ, cho PhotoService , chúng tôi sẽ chỉ có hai phương pháp:
- addPhoto () - để tải lên một Ảnh sang MongoDB
- getPhoto () - để truy xuất Ảnh với một id đã cho
@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. Tải lên tệp lớn
Bây giờ, chúng tôi sẽ sử dụng GridFS để tải lên và truy xuất các tệp lớn.
Đầu tiên, chúng tôi sẽ xác định DTO - Video đơn giản - đại diện cho một tệp lớn:
public class Video {
private String title;
private InputStream stream;
}
Tương tự với PhotoService , chúng tôi sẽ có một VideoService bằng hai phương pháp - addVideo () và 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;
}
}
Để biết thêm chi tiết về cách sử dụng GridFS với Spring, hãy xem bài viết GridFS trong Spring Data MongoDB của chúng tôi.
6. Bộ điều khiển
Bây giờ, chúng ta hãy xem xét các bộ điều khiển - PhotoController và VideoController .
6.1. PhotoController
Đầu tiên, chúng tôi có PhotoController, sẽ sử dụng PhotoService của chúng tôi để thêm / lấy ảnh .
Chúng tôi sẽ xác định addPhoto () để tải lên và tạo một Ảnh mới :
@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;
}
Chúng tôi cũng có getPhoto () để truy xuất Ảnh có id đã cho:
@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";
}
Lưu ý rằng khi chúng tôi có dữ liệu hình ảnh được trả về dưới dạng byte [] , chúng tôi sẽ chuyển đổi nó thành Base64 Chuỗi để hiển thị nó trên giao diện người dùng.
6.2. VideoController
Tiếp theo, hãy xem qua VideoController của chúng tôi .
Điều này sẽ có một phương thức tương tự, addVideo () , Để tải lên một Video tới MongoDB của chúng tôi:
@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;
}
Và ở đây chúng tôi có getVideo () để truy xuất Video với một id đã cho :
@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";
}
Chúng tôi cũng có thể thêm một streamVideo () phương pháp sẽ tạo URL phát trực tuyến từ 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. Giao diện người dùng
Cuối cùng, hãy xem giao diện người dùng của chúng tôi.
Hãy bắt đầu với uploadPhoto.html , cung cấp một biểu mẫu đơn giản để tải lên hình ảnh:
<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>
Tiếp theo, chúng tôi sẽ thêm photos.html xem để hiển thị ảnh của chúng tôi:
<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>
Tương tự, chúng tôi có uploadVideo.html để tải lên một 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>
Và videos.html để hiển thị 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>