GridFS 是用于存储和检索超过16 MB BSON 文档大小限制的文件的规范。 GridFS 不是将大文件存储在单个文档中,而是将文件划分为多个部分或数据段,并将每个数据段存储为单独的文档。
当您在 GridFS 存储中查询文件时,驱动程序会根据需要重新组合数据段。
此指南中的代码示例来自驱动程序源代码 GitHub 存储库中的 GridFSTour.java 文件。
先决条件
您必须在程序中包含以下 import 语句才能运行本指南中的代码示例:
import com.mongodb.reactivestreams.client.MongoClients;import com.mongodb.reactivestreams.client.MongoClient;import com.mongodb.reactivestreams.client.MongoDatabase;
import com.mongodb.client.gridfs.model.*;import com.mongodb.reactivestreams.client.gridfs.*;
import org.bson.Document;import org.bson.types.ObjectId;
import java.io.FileNotFoundException;import java.io.IOException;import java.nio.Buffer;import java.nio.ByteBuffer;import java.nio.charset.StandardCharsets;
import static com.mongodb.client.model.Filters.eq;import static reactivestreams.helpers.PublisherHelpers.toPublisher;重要
本指南使用自定义Subscriber实现,如《自定义订阅服务器实现示例》指南中所述。
连接到 MongoDB 部署
首先,连接到 MongoDB 部署并声明和定义一个MongoDatabase实例。
以下代码连接到在端口27017上的localhost上运行的独立 MongoDB 部署:
MongoClient mongoClient = MongoClients.create();要了解有关连接到 MongoDB 部署的更多信息,请参阅连接到 MongoDB教程。
创建 GridFS 存储桶
GridFS 将文件存储在两个集合中:
chunks:存储文件数据段files:存储文件元数据
这两个集合位于同一存储桶中,并且集合名称以存储桶名称为前缀。
驱动程序提供了GridFSBuckets.create()方法来创建GridFSBucket实例:
MongoDatabase myDatabase = mongoClient.getDatabase("mydb");
// Create a gridFSBucket using the default bucket name "fs"GridFSBucket gridFSBucket = GridFSBuckets.create(myDatabase);注意
当您将数据上传到 GridFS 存储桶时,GridFS 会自动在files和chunks集合上创建索引。
您可以将存储桶名称传递给GridFSBuckets.create()方法:
// Create a gridFSBucket with a custom bucket name "files"GridFSBucket gridFSFilesBucket = GridFSBuckets.create(myDatabase, "files");提示
超时设置
您可以使用客户端操作超时 (CSOT) 设置来限制服务器完成GridFS操作的时间。要学习;了解有关将此设置与GridFS一起使用的更多信息,请参阅限制服务器执行时间指南中的GridFS部分。
上传到 GridFS
GridFSBucket.uploadFromPublisher()方法读取Publisher<ByteBuffer>的内容并将其保存到GridFSBucket实例。
您可以使用GridFSUploadOptions类型来配置数据段大小或包含其他元数据。
以下示例将Publisher<ByteBuffer>的内容上传到GridFSBucket :
// Get the input publisherPublisher<ByteBuffer> publisherToUploadFrom = toPublisher( ByteBuffer .wrap("MongoDB Tutorial..".getBytes(StandardCharsets.UTF_8)));
// Create some custom optionsGridFSUploadOptions options = new GridFSUploadOptions() .chunkSizeBytes(1024) .metadata(new Document("type", "presentation"));
ObservableSubscriber<ObjectId> uploadSubscriber = new OperationSubscriber<>();gridFSBucket.uploadFromPublisher("mongodb-tutorial", publisherToUploadFrom, options).subscribe(uploadSubscriber);ObjectId fileId = uploadSubscriber.get().get(0);查找存储在 GridFS 中的文件
要查找存储在GridFSBucket中的文件,请使用find()方法。
以下示例打印出存储的每个文件的文件名:
ConsumerSubscriber<GridFSFile> filesSubscriber = new ConsumerSubscriber<>(gridFSFile -> System.out.println(" - " + gridFSFile.getFilename()));gridFSBucket.find().subscribe(filesSubscriber);filesSubscriber.await();您还可以提供自定义筛选器来限制返回的结果。 以下示例打印用户定义的元数据文档中contentType值为image/png值的所有文件的文件名:
filesSubscriber = new ConsumerSubscriber<>(gridFSFile -> System.out.println("Found: " + gridFSFile.getFilename()));gridFSBucket.find(eq("metadata.contentType", "image/png")).subscribe(filesSubscriber);filesSubscriber.await();从 GridFS 下载
downloadToPublisher()方法返回一个Publisher<ByteBuffer> ,用于从 MongoDB 读取内容。
要通过文件_id下载文件,请将_id传递给该方法。 以下示例通过文件_id下载文件:
ObjectId fileId;ObservableSubscriber<ByteBuffer> downloadSubscriber = new OperationSubscriber<>();gridFSBucket.downloadToPublisher(fileId).subscribe(downloadSubscriber);如果您不知道文件的_id ,但知道文件名,则可以将文件名传递给downloadToPublisher()方法。 默认情况下,它将下载该文件的最新版本。 使用GridFSDownloadOptions类配置要下载的版本。
以下示例下载名为mongodb-tutorial的文件的原始版本:
GridFSDownloadOptions downloadOptions = new GridFSDownloadOptions().revision(0);downloadSubscriber = new OperationSubscriber<>();gridFSBucket.downloadToPublisher("mongodb-tutorial", downloadOptions).subscribe(downloadSubscriber);重命名文件
如果需要重命名文件,请使用rename()方法。
如下示例将一个文件重命名为 mongodbTutorial:
ObjectId fileId; //ObjectId of a file uploaded to GridFSgridFSBucket.rename(fileId, "mongodbTutorial").subscribe(new ObservableSubscriber<Void>());注意
rename()方法需要ObjectId而不是filename ,以确保重命名正确的文件。
要重命名同一文件名的多个修订版本,请先检索文件的完整列表。 然后,对于应重命名的每个文件,使用相应的 运行rename() _id。
删除文件
要从GridFSBucket中删除文件,请使用delete()方法。
以下示例从GridFSBucket中删除一个文件:
ObjectId fileId; //ObjectId of a file uploaded to GridFSgridFSBucket.delete(fileId).subscribe(new ObservableSubscriber<Void>());