Upload and Retrieve Files Using MongoDB and Spring Boot – 使用MongoDB和Spring Boot上传和检索文件

最后修改: 2019年 7月 13日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll discuss how to upload and retrieve files using MongoDB and Spring Boot.

在本教程中,我们将讨论如何使用MongoDB和Spring Boot上传和检索文件。

We’ll use MongoDB BSON for small files and GridFS for the larger ones.

我们将使用MongoDB的BSON来处理小文件,GridFS来处理大文件。

2. Maven Configuration

2.Maven配置

First, we’ll add the spring-boot-starter-data-mongodb dependency to our pom.xml:

首先,我们将把spring-boot-starter-data-mongodb依赖性添加到我们的pom.xml

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

In addition, we’ll need the spring-boot-starter-web and spring-boot-starter-thymeleaf dependencies to display the user interface of our application. These dependencies are also shown in our Guide to Spring Boot with Thymeleaf.

此外,我们还需要spring-boot-starter-webspring-boot-starter-thymeleaf依赖项来显示我们应用程序的用户界面。这些依赖项也在我们的Guide to Spring Boot with Thymeleaf中显示。

In this tutorial, we’re using Spring Boot version 2.x.

在本教程中,我们使用的是Spring Boot 2.x版本。

3. Spring Boot Properties

3.Spring Boot属性

Next, we’ll configure the necessary Spring Boot properties.

接下来,我们将配置必要的Spring Boot属性。

Let’s start with the MongoDB properties:

让我们从MongoDB的属性开始。

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

We’ll also set the Servlet Multipart properties to allow uploading large files:

我们还将设置Servlet Multipart属性,以允许上传大型文件:

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

4. Uploading Small Files

4.上传小文件

Now, we’ll discuss how to upload and retrieve small files (size < 16MB) using MongoDB BSON.

现在,我们将讨论如何使用MongoDB BSON上传和检索小文件(大小<16MB)。

Here, we have a simple Document class — Photo. We’ll store our image file in a BSON Binary:

在这里,我们有一个简单的Document类–Photo. 我们将把我们的图片文件存储在一个BSON Binary

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

And we’ll have a simple PhotoRepository:

而我们将有一个简单的PhotoRepository

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

Now, for the PhotoService, we’ll have only two methods:

现在,对于PhotoService,我们将只有两个方法。

  • addPhoto() — to upload a Photo to MongoDB
  • getPhoto() — to retrieve a Photo with a given 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. Uploading Large Files

5.上传大文件

Now, we’ll use GridFS to upload and retrieve large files.

现在,我们将使用GridFS来上传和检索大文件。

First, we’ll define a simple DTO – Video – to represent a large file:

首先,我们将定义一个简单的DTO–Video–来代表一个大文件。

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

Similar to the PhotoService, we’ll have a VideoService with two methods — addVideo() and getVideo():

PhotoService类似,我们将有一个VideoService,有两个方法 – addVideo()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; 
    }
}

For more details on using GridFS with Spring, check our GridFS in Spring Data MongoDB article.

有关在 Spring 中使用GridFS的更多细节,请查看我们的GridFS in Spring Data MongoDB文章。

6. Controllers

6.控制器

Now, let’s take a look at the controllers — PhotoController and VideoController.

现在,让我们来看看控制器–PhotoControllerVideoController

6.1. PhotoController

6.1.PhotoController

First, we have the PhotoController, which will use our PhotoService to add/get photos.

首先,我们有PhotoController,它将使用我们的PhotoService来添加/获取照片

We’ll define the addPhoto() method to upload and create a new Photo:

我们将定义addPhoto()方法来上传和创建一个新的Photo

@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 also have getPhoto() to retrieve a Photo with a given id:

我们也有getPhoto()来检索一个具有给定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";
}

Note that as we have the image data returned as a byte[], we’ll convert it to a Base64 String to display it on the front-end.

注意,由于我们的图像数据以byte[]形式返回,我们将把它转换为Base64 String,以便在前端显示它。

6.2. VideoController

6.2.VideoController

Next, let’s have a look at our VideoController.

接下来,让我们看一下我们的VideoController

This will have a similar method, addVideo(), to upload a Video to our MongoDB:

这将有一个类似的方法,addVideo(),以上传Video到我们的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;
}

And here we have getVideo() to retrieve a Video with a given id:

在这里,我们有getVideo()来检索一个具有给定idVideo

@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 can also add a streamVideo() method that will create a streaming URL from the Video InputStream:

我们还可以添加一个streamVideo()方法,它将从VideoInputStream创建一个流媒体URL。

@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

7.前端

Finally, let’s see our front-end.
Let’s start with uploadPhoto.html, which provides a simple form to upload an image:

最后,让我们看看我们的前端。
让我们从uploadPhoto.html开始,它提供了一个简单的表单来上传图片。

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

Next, we’ll add the photos.html view to display our photos:

接下来,我们将添加photos.html视图来显示我们的照片。

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

Similarly, we have the uploadVideo.html to upload a Video:

同样,我们有uploadVideo.html来上传一个视频

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

And videos.html to display videos:

还有videos.html来显示视频。

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

8. Conclusion

8.结论

In this article, we learned how to upload and retrieve files using MongoDB and Spring Boot. We used both BSON and GridFS to upload and retrieve files.

在这篇文章中,我们学习了如何使用MongoDB和Spring Boot上传和检索文件。我们同时使用BSONGridFS来上传和检索文件。

As always, the full source code is available in the GitHub project.

一如既往,完整的源代码可在GitHub项目中获得。