| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 | 
							- var path = Npm.require('path');
 
- var mongodb = Npm.require('mongodb');
 
- var ObjectID = Npm.require('mongodb').ObjectID;
 
- var Grid = Npm.require('gridfs-stream');
 
- //var Grid = Npm.require('gridfs-locking-stream');
 
- var chunkSize = 1024*1024*2; // 256k is default GridFS chunk size, but performs terribly for largish files
 
- /**
 
-  * @public
 
-  * @constructor
 
-  * @param {String} name - The store name
 
-  * @param {Object} options
 
-  * @param {Function} [options.beforeSave] - Function to run before saving a file from the server. The context of the function will be the `FS.File` instance we're saving. The function may alter its properties.
 
-  * @param {Number} [options.maxTries=5] - Max times to attempt saving a file
 
-  * @returns {FS.StorageAdapter} An instance of FS.StorageAdapter.
 
-  *
 
-  * Creates a GridFS store instance on the server. Inherits from FS.StorageAdapter
 
-  * type.
 
-  */
 
- FS.Store.GridFS = function(name, options) {
 
-   var self = this;
 
-   options = options || {};
 
-   var gridfsName = name;
 
-   var mongoOptions = options.mongoOptions || {};
 
-   if (!(self instanceof FS.Store.GridFS))
 
-     throw new Error('FS.Store.GridFS missing keyword "new"');
 
-   if (!options.mongoUrl) {
 
-     options.mongoUrl = process.env.MONGO_URL;
 
-     // When using a Meteor MongoDB instance, preface name with "cfs_gridfs."
 
-     gridfsName = "cfs_gridfs." + name;
 
-   }
 
-   if (!options.mongoOptions) {
 
-     options.mongoOptions = { db: { native_parser: true }, server: { auto_reconnect: true }};
 
-   }
 
-   if (options.chunkSize) {
 
-     chunkSize = options.chunkSize;
 
-   }
 
-   return new FS.StorageAdapter(name, options, {
 
-     typeName: 'storage.gridfs',
 
-     fileKey: function(fileObj) {
 
-       // We should not have to mount the file here - We assume its taken
 
-       // care of - Otherwise we create new files instead of overwriting
 
-       var key = {
 
-         _id: null,
 
-         filename: null
 
-       };
 
-       // If we're passed a fileObj, we retrieve the _id and filename from it.
 
-       if (fileObj) {
 
-         var info = fileObj._getInfo(name, {updateFileRecordFirst: false});
 
-         key._id = info.key || null;
 
-         key.filename = info.name || fileObj.name({updateFileRecordFirst: false}) || (fileObj.collectionName + '-' + fileObj._id);
 
-       }
 
-       // If key._id is null at this point, createWriteStream will let GridFS generate a new ID
 
-       return key;
 
-     },
 
-     createReadStream: function(fileKey, options) {
 
-       options = options || {};
 
-       // Init GridFS
 
-       var gfs = new Grid(self.db, mongodb);
 
-       // Set the default streamning settings
 
-       var settings = {
 
-         _id: new ObjectID(fileKey._id),
 
-         root: gridfsName
 
-       };
 
-       // Check if this should be a partial read
 
-       if (typeof options.start !== 'undefined' && typeof options.end !== 'undefined' ) {
 
-         // Add partial info
 
-         settings.range = {
 
-           startPos: options.start,
 
-           endPos: options.end
 
-         };
 
-       }
 
-       FS.debug && console.log('GRIDFS', settings);
 
-       return gfs.createReadStream(settings);
 
-     },
 
-     createWriteStream: function(fileKey, options) {
 
-       options = options || {};
 
-       // Init GridFS
 
-       var gfs = new Grid(self.db, mongodb);
 
-       var opts = {
 
-         filename: fileKey.filename,
 
-         mode: 'w',
 
-         root: gridfsName,
 
-         chunk_size: options.chunk_size || chunkSize,
 
-         // We allow aliases, metadata and contentType to be passed in via
 
-         // options
 
-         aliases: options.aliases || [],
 
-         metadata: options.metadata || null,
 
-         content_type: options.contentType || 'application/octet-stream'
 
-       };
 
-       if (fileKey._id) {
 
-         opts._id = new ObjectID(fileKey._id);
 
-       }
 
-       var writeStream = gfs.createWriteStream(opts);
 
-       writeStream.on('close', function(file) {
 
-         if (!file) {
 
-           // gridfs-stream will emit "close" without passing a file
 
-           // if there is an error. We can simply exit here because
 
-           // the "error" listener will also be called in this case.
 
-           return;
 
-         }
 
-         if (FS.debug) console.log('SA GridFS - DONE!');
 
-         // Emit end and return the fileKey, size, and updated date
 
-         writeStream.emit('stored', {
 
-           // Set the generated _id so that we know it for future reads and writes.
 
-           // We store the _id as a string and only convert to ObjectID right before
 
-           // reading, writing, or deleting. If we store the ObjectID itself,
 
-           // Meteor (EJSON?) seems to convert it to a LocalCollection.ObjectID,
 
-           // which GFS doesn't understand.
 
-           fileKey: file._id.toString(),
 
-           size: file.length,
 
-           storedAt: file.uploadDate || new Date()
 
-         });
 
-       });
 
-       writeStream.on('error', function(error) {
 
-         console.log('SA GridFS - ERROR!', error);
 
-       });
 
-       return writeStream;
 
-     },
 
-     remove: function(fileKey, callback) {
 
-       // Init GridFS
 
-       var gfs = new Grid(self.db, mongodb);
 
-       try {
 
-         gfs.remove({ _id: new ObjectID(fileKey._id), root: gridfsName }, callback);
 
-       } catch(err) {
 
-         callback(err);
 
-       }
 
-     },
 
-     // Not implemented
 
-     watch: function() {
 
-       throw new Error("GridFS storage adapter does not support the sync option");
 
-     },
 
-     init: function(callback) {
 
-       mongodb.MongoClient.connect(options.mongoUrl, mongoOptions, function (err, db) {
 
-         if (err) { return callback(err); }
 
-         self.db = db;
 
-         
 
-         // ensure that indexes are added as otherwise CollectionFS fails for Mongo >= 3.0
 
-         var collection = new Mongo.Collection(gridfsName);
 
-         collection.rawCollection().ensureIndex({ "files_id": 1, "n": 1});        
 
-         
 
-         callback(null);
 
-       });
 
-     }
 
-   });
 
- };
 
 
  |