MongoDB - GridFS
MongoDB - GridFS
Section titled “MongoDB - GridFS”GridFS 是 MongoDB 中用于存储和检索超出 BSON 文档大小限制(16 MB)文件的规范。GridFS 不会将文件存储在单个文档中,而是将文件分割成更小的部分,即分块(chunks),并将每个分块作为单独的文档存储。这允许将视频、高分辨率图像或大量日志文件等大型文件直接存储在 MongoDB 数据库中。
默认情况下,GridFS 使用两个集合来管理文件:fs.files 和 fs.chunks。
- fs.files:此集合存储文件的元数据(metadata)。此集合中的每个文档代表一个文件,并包含
filename(文件名)、chunkSize(分块大小)、uploadDate(上传日期)以及自定义元数据等信息。 - fs.chunks:此集合存储文件的二进制分块。每个分块通过
files_id字段链接回其父文件,该字段对应于fs.files集合中文档的_id。
元数据文档示例 (fs.files)
Section titled “元数据文档示例 (fs.files)”此文档包含有关所存储文件的高级信息。
{ "_id": ObjectId("64f7c2f1b3e9a1e8a8b1a8d5"), "length": 10485760, // 文件的总大小(字节) "chunkSize": 261120, // 每个分块的大小(字节,默认 255k) "uploadDate": ISODate("2023-09-06T00:00:00.000Z"), "filename": "large_video.mp4", "contentType": "video/mp4", // 可选:用户自定义元数据 "metadata": { "author": "John Doe" } // 可选:用户自定义元数据}分块文档示例 (fs.chunks)
Section titled “分块文档示例 (fs.chunks)”此文档包含实际文件数据的一部分。
{ "_id": ObjectId("64f7c300b3e9a1e8a8b1a8d6"), "files_id": ObjectId("64f7c2f1b3e9a1e8a8b1a8d5"), // 链接到 fs.files 文档 "n": 0, // 分块的序列号(基于 0) "data": BinData(0, "...binary data of the chunk...") // 实际数据}以编程方式使用 GridFS (Node.js)
Section titled “以编程方式使用 GridFS (Node.js)”虽然 mongofiles 命令行工具可用于手动操作,但大多数现代应用程序通过 MongoDB 驱动程序以编程方式与 GridFS 交互。以下示例演示了如何使用官方 Node.js 驱动程序上传和下载文件。
首先,确保您已在项目中安装 Node.js 驱动程序:
npm install mongodb示例:上传和下载文件
Section titled “示例:上传和下载文件”此代码片段展示了如何连接到数据库,将文件从本地文件系统上传到 GridFS,然后将其下载回来。
const { MongoClient } = require('mongodb');const fs = require('fs');const path = require('path');
async function main() { const uri = 'mongodb://localhost:27017'; const client = new MongoClient(uri);
try { await client.connect(); const database = client.db('myGridFSDB'); const bucket = new mongodb.GridFSBucket(database);
const filename = 'example.txt'; const filepath = path.join(__dirname, filename);
// 创建一个示例文件以上传 fs.writeFileSync(filepath, 'Hello, GridFS!');
// 1. 将文件上传到 GridFS const uploadStream = bucket.openUploadStream(filename, { chunkSizeBytes: 1024, // 自定义分块大小 metadata: { owner: 'system' } }); const readStream = fs.createReadStream(filepath); readStream.pipe(uploadStream);
console.log(`文件 '${filename}' 上传成功。`);
// 2. 从 GridFS 下载文件 const downloadStream = bucket.openDownloadStreamByName(filename); const downloadedFilepath = path.join(__dirname, 'downloaded_example.txt'); const writeStream = fs.createWriteStream(downloadedFilepath); downloadStream.pipe(writeStream);
writeStream.on('finish', () => { console.log(`文件 '${filename}' 下载成功。`); client.close(); });
} catch (e) { console.error('发生错误:', e); await client.close(); }}
main().catch(console.error);何时使用 GridFS
Section titled “何时使用 GridFS”- 当您需要存储大于 16 MB 的文件时。
- 当您希望将文件及其元数据一起存储在 MongoDB 中,而不是使用单独的文件存储系统(如 AWS S3 或本地文件系统)时。
- 当您想访问文件的部分内容而无需将整个文件加载到内存中时(例如,流式传输视频或查找大型日志文件的特定部分)。
对于许多用例,特别是在云原生应用程序中,将大文件存储在专用的对象存储服务(如 Amazon S3 或 Google Cloud Storage)中可能更具成本效益和可扩展性。在这种情况下,您将在 MongoDB 文档中存储指向该对象的 URL 或标识符,而不是文件本身。