Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /

Almacena archivos grandes mediante GridFS

En esta guía, puedes aprender cómo almacenar y recuperar archivos grandes en MongoDB utilizando GridFS. GridFS es una especificación implementada por el driver de C++ que describe cómo dividir archivos en fragmentos al almacenarlos y reorganizarlos al recuperarlos. La implementación de GridFS en el driver es una abstracción que gestiona las operaciones y la organización del almacenamiento de archivos.

Utiliza GridFS si el tamaño de tus archivos excede el límite de tamaño del documento BSON de 16MB. Para obtener información más detallada sobre si GridFS es adecuado para su caso de uso, consulte GridFS en el manual del MongoDB Server.

GridFS organiza los archivos en un bucket, un grupo de colecciones de MongoDB que contienen los fragmentos de archivos e información que los describe. El bucket contiene las siguientes colecciones, nombradas según la convención definida en la especificación GridFS:

  • chunks colección, que almacena los fragmentos de archivo binario

  • files colección, que almacena los metadatos del archivo

El driver crea el bucket de GridFS, si no existe, cuando se guardan por primera vez datos en él. El bucket contiene las colecciones anteriores con el prefijo del nombre de bucket por defecto fs, a menos que especifiques un nombre diferente. Para asegurar la recuperación eficiente de los archivos y metadatos relacionados, el controlador crea un índice en cada colección. El driver asegura que estos índices existan antes de realizar operaciones de lectura y escritura en el bucket de GridFS.

Para obtener más información sobre los índices de GridFS, consulta Índices de GridFS en el manual del servidor MongoDB.

Cuando se utiliza GridFS para almacenar archivos, el driver divide los archivos en fragmentos más pequeños, cada uno representado por un documento independiente en la colección chunks. También crea un documento en la colección files que contiene un ID de archivo, nombre de archivo y otros metadatos del archivo. Puedes cargar el archivo pasando un flujo al controlador de C++ para que lo procese o crear un nuevo flujo y escribir directamente en él.

El siguiente diagrama muestra cómo GridFS divide los archivos cuando se cargan en un bucket.

Un diagrama que muestra cómo GridFS sube un archivo a un bucket

Al recuperar archivos, GridFS obtiene los metadatos de la colección files en el bucket especificado y utiliza la información para reconstruir el archivo a partir de los documentos en la colección chunks. Se puede leer el archivo escribiendo su contenido en un flujo existente o creando un nuevo flujo que apunte al archivo.

Para empezar a almacenar o recuperar archivos de GridFS, llama al método gridfs_bucket() en tu base de datos. Este método accede a un bucket existente o crea uno nuevo si aún no existe.

El siguiente ejemplo llama al método gridfs_bucket() en la base de datos db:

auto bucket = db.gridfs_bucket();

Puedes personalizar la configuración del bucket de GridFS pasando una instancia de la clase mongocxx::options::gridfs::bucket como un argumento opcional al método gridfs_bucket(). La siguiente tabla describe los campos que puedes configurar en una instancia de mongocxx::options::gridfs::bucket:

Campo
Descripción

bucket_name

Specifies the bucket name to use as a prefix for the files and chunks collections. The default value is "fs".
Type: std::string

chunk_size_bytes

Specifies the chunk size that GridFS splits files into. The default value is 261120.
Type: std::int32_t

read_concern

Specifies the read concern to use for bucket operations. The default value is the database's read concern.
Type: mongocxx::read_concern

read_preference

Specifies the read preference to use for bucket operations. The default value is the database's read preference.
Type: mongocxx::read_preference

write_concern

Specifies the write concern to use for bucket operations. The default value is the database's write concern.
Type: mongocxx::write_concern

El siguiente ejemplo crea un bucket llamado "myCustomBucket" configurando el campo bucket_name de una instancia mongocxx::options::gridfs::bucket:

mongocxx::options::gridfs::bucket opts;
opts.bucket_name("myCustomBucket");
auto bucket = db.gridfs_bucket(opts);

Puede cargar archivos en un bucket de GridFS utilizando los siguientes métodos:

Utiliza el método open_upload_stream() para crear una secuencia de subida para un nombre de archivo determinado. El método open_upload_stream() permite especificar información de configuración en una instancia options::gridfs::upload, la cual se puede pasar como parámetro.

Este ejemplo utiliza una transmisión de carga para realizar las siguientes acciones:

  • Establece el campo chunk_size_bytes de una instancia de opciones

  • Abre una secuencia grabable para un nuevo archivo GridFS llamado "my_file" y aplica la opción chunk_size_bytes

  • Llama al método write() para guardar datos en my_file, a la que apunta el flujo.

  • Llama al método close() para cerrar el flujo que apunta a my_file

mongocxx::options::gridfs::upload opts;
opts.chunk_size_bytes(1048576);
auto uploader = bucket.open_upload_stream("my_file", opts);
// ASCII for "HelloWorld"
std::uint8_t bytes[10] = {72, 101, 108, 108, 111, 87, 111, 114, 108, 100};
for (auto i = 0; i < 5; ++i) {
uploader.write(bytes, 10);
}
uploader.close();

Utilice el método upload_from_stream() para cargar el contenido de una secuencia a un nuevo archivo GridFS. El método upload_from_stream() permite especificar información de configuración en una instancia options::gridfs::upload, que puede pasar como parámetro.

Este ejemplo realiza las siguientes acciones:

  • Abre un archivo ubicado en /path/to/input_file como un flujo en modo de lectura binaria

  • Llama al método upload_from_stream() para cargar el contenido del flujo en un archivo GridFS llamado "new_file"

std::ifstream file("/path/to/input_file", std::ios::binary);
bucket.upload_from_stream("new_file", &file);

En esta sección, puedes aprender a recuperar metadatos de archivos almacenados en la colección files del depósito de GridFS. Los metadatos contienen información sobre el archivo al que se refieren, incluyendo:

  • El _id del archivo

  • El nombre del archivo

  • La longitud/tamaño del archivo

  • La fecha y hora de carga

  • Un documento metadata en el que puedes almacenar otra información

Para recuperar archivos de un bucket de GridFS, se debe llamar al método mongocxx::gridfs::bucket::find() en el bucket. El método devuelve una instancia de mongocxx::cursor desde la cual puede acceder a los resultados. Para saber más sobre los cursores, consulta el Guíade acceso a datos desde un cursor.

El siguiente ejemplo de código muestra cómo recuperar e imprimir los metadatos de archivos de un bucket GridFS. Utiliza un bucle for para recorrer el cursor devuelto y mostrar el contenido de los archivos subidos en los ejemplos Subir Archivos:

auto cursor = bucket.find({});
for (auto&& doc : cursor) {
std::cout << bsoncxx::to_json(doc) << std::endl;
}
{ "_id" : { "$oid" : "..." }, "length" : 13, "chunkSize" : 261120, "uploadDate" :
{ "$date" : ... }, "filename" : "new_file" }
{ "_id" : { "$oid" : "..." }, "length" : 50, "chunkSize" : 1048576, "uploadDate" :
{ "$date" : ... }, "filename" : "my_file" }

El find() método acepta varias especificaciones de consulta. Puede usar su mongocxx::options::find parámetro para especificar el orden de clasificación, el número máximo de documentos a devolver y el número de documentos que se omitirán antes de devolver. Para ver una lista de las opciones disponibles, consulte la documentación de la API.

Puede descargar archivos de un bucket GridFS utilizando los siguientes métodos:

Puedes descargar archivos de tu base de datos MongoDB utilizando el método open_download_stream() para crear un flujo de descarga.

Este ejemplo utiliza un flujo de descarga para realizar las siguientes acciones:

  • Recupera el valor _id del archivo GridFS llamado "new_file"

  • Pasa el valor _id al método open_download_stream() para abrir el archivo como un flujo legible

  • Crea un vector buffer para almacenar el contenido del archivo

  • Llama al método read() para leer el contenido del archivo desde el flujo downloader al vector

auto doc = db["fs.files"].find_one(make_document(kvp("filename", "new_file")));
auto id = doc->view()["_id"].get_value();
auto downloader = bucket.open_download_stream(id);
std::vector<uint8_t> buffer(downloader.file_length());
downloader.read(buffer.data(), buffer.size());

Puedes descargar el contenido de un archivo GridFS a un flujo existente llamando al método download_to_stream() en tu contenedor.

Este ejemplo realiza las siguientes acciones:

  • Abre un archivo ubicado en /path/to/output_file como un flujo en modo binario de escritura

  • Recupera el valor _id del archivo GridFS llamado "new_file"

  • Pasa el valor _id a download_to_stream() para descargar el archivo al flujo

std::ofstream output_file("/path/to/output_file", std::ios::binary);
auto doc = db["fs.files"].find_one(make_document(kvp("filename", "new_file")));
auto id = doc->view()["_id"].get_value();
bucket.download_to_stream(id, &output_file);

Utilice el método delete_file() para eliminar el documento de colección de un archivo y los fragmentos asociados de su bucket. Esto elimina el archivo. Debe especificar el archivo por su campo _id en lugar de por su nombre.

El siguiente ejemplo muestra cómo borrar un archivo llamado "my_file" pasando su valor _id a delete_file():

auto doc = db["fs.files"].find_one(make_document(kvp("filename", "my_file")));
auto id = doc->view()["_id"].get_value();
bucket.delete_file(id);

Nota

Revisiones de archivos

El método delete_file() solo admite la eliminación de un archivo a la vez. Si deseas borrar cada versión de archivo, o archivos con diferentes tiempos de carga que comparten el mismo nombre de archivo, recopila los valores de _id de cada versión. A continuación, pasa cada valor de _id en llamadas separadas al método delete_file().

Para obtener más información sobre cómo usar el controlador de C++ para almacenar y recuperar archivos grandes, consulta la siguiente documentación de la API:

Volver

Transacciones

En esta página