GridFS
GridFS是一种用于存储和检索超出16MB BSON文档大小限制的文件的规范。与将大文件存储在一个单独的文档中不同,GridFS将文件分成多个部分或块,并将每个块作为单独的文档存储。
当你查询GridFS存储中的文件时,驱动程序会根据需要重新组装这些块。
本指南中的代码示例来自GridFSTour.java 文件位于驱动源代码 GitHub 仓库中。
先决条件
您必须在程序中包含以下导入语句,才能运行本指南中的代码示例
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
实例。
以下代码连接到在 localhost
上运行的独立 MongoDB 部署的 27017
端口
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);
您可以将存储桶名称传递给GridFSBuckets.create()
方法
// Create a gridFSBucket with a custom bucket name "files" GridFSBucket gridFSFilesBucket = GridFSBuckets.create(myDatabase, "files");
注意
当您将数据上传到GridFS存储桶时,GridFS会自动在files
和chunks
集合上创建索引。
上传到GridFS
GridFSBucket.uploadFromPublisher()
方法读取Publisher<ByteBuffer>
的内容并将其保存到GridFSBucket
实例中。
您可以使用GridFSUploadOptions
类型来配置块大小或包含额外的元数据。
以下示例将Publisher<ByteBuffer>
的内容上传到GridFSBucket
。
// Get the input publisher Publisher<ByteBuffer> publisherToUploadFrom = toPublisher( ByteBuffer .wrap("MongoDB Tutorial..".getBytes(StandardCharsets.UTF_8)) ); // Create some custom options GridFSUploadOptions 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 GridFS gridFSBucket.rename(fileId, "mongodbTutorial").subscribe(new ObservableSubscriber<Void>());
注意
rename()
方法需要 ObjectId
而不是 filename
,以确保正确重命名文件。
要重命名相同文件名的多个版本,首先检索完整的文件列表。然后,对于每个需要重命名的文件,使用相应的 _id
运行 rename()
。
删除文件
要从 GridFSBucket
删除文件,请使用 delete()
方法。
以下示例演示如何从GridFSBucket
删除文件。
ObjectId fileId; //ObjectId of a file uploaded to GridFS gridFSBucket.delete(fileId).subscribe(new ObservableSubscriber<Void>());