/** GridFSBucketAdapter Stores files in Mongo using GridStore Requires the database adapter to be based on mongoclient @flow weak */ // @flow-disable-next import { MongoClient, GridFSBucket, Db } from 'mongodb'; import { FilesAdapter } from './FilesAdapter'; import defaults from '../../defaults'; export class GridFSBucketAdapter extends FilesAdapter { _databaseURI: string; _connectionPromise: Promise; _mongoOptions: Object; constructor(mongoDatabaseURI = defaults.DefaultMongoURI, mongoOptions = {}) { super(); this._databaseURI = mongoDatabaseURI; const defaultMongoOptions = { useNewUrlParser: true }; this._mongoOptions = Object.assign(defaultMongoOptions, mongoOptions); } _connect() { if (!this._connectionPromise) { this._connectionPromise = MongoClient.connect( this._databaseURI, this._mongoOptions ).then(client => client.db(client.s.options.dbName)); } return this._connectionPromise; } _getBucket() { return this._connect().then(database => new GridFSBucket(database)); } // For a given config object, filename, and data, store a file // Returns a promise async createFile(filename: string, data) { const bucket = await this._getBucket(); const stream = await bucket.openUploadStream(filename); await stream.write(data); stream.end(); return new Promise((resolve, reject) => { stream.on('finish', resolve); stream.on('error', reject); }); } async deleteFile(filename: string) { const bucket = await this._getBucket(); const documents = await bucket.find({ filename: filename }).toArray(); if (documents.length === 0) { throw new Error('FileNotFound'); } return Promise.all( documents.map(doc => { return bucket.delete(doc._id); }) ); } async getFileData(filename: string) { const stream = await this.getDownloadStream(filename); stream.read(); return new Promise((resolve, reject) => { const chunks = []; stream.on('data', data => { chunks.push(data); }); stream.on('end', () => { resolve(Buffer.concat(chunks)); }); stream.on('error', err => { reject(err); }); }); } getFileLocation(config, filename) { return ( config.mount + '/files/' + config.applicationId + '/' + encodeURIComponent(filename) ); } async getDownloadStream(filename: string) { const bucket = await this._getBucket(); return bucket.openDownloadStreamByName(filename); } } export default GridFSBucketAdapter;