@onehilltech/blueprint
Version:
lightweight, simple, elegant framework for building mean applications
217 lines (176 loc) • 5.11 kB
JavaScript
var util = require ('util')
, path = require ('path')
, Framework = require ('./Framework')
, mongodb = require ('mongodb')
, multer = require ('multer')
, winston = require ('winston')
, async = require ('async')
, fs = require ('fs')
;
var BaseController = require ('./BaseController')
, HttpError = require ('./errors/HttpError')
;
function GridFSController (opts) {
BaseController.call (this);
opts = opts || {};
if (!opts.name)
throw new Error ('Options must define id property');
this._name = opts.name;
if (!opts.id)
this._id = opts.name + 'Id';
this._resolveUser = opts.resolveUser;
// Define how we are going to accept uploads.
this._uploadPath = opts.uploadPath || path.resolve (Framework().app.appPath, 'temp/uploads');
this._upload = multer ({dest: this._uploadPath});
var self = this;
Framework ().messaging.once ('app.init', function (app) {
var conn = app.database.conn;
conn.on ('open', function () {
var opts = { bucketName: self._name };
self._bucket = new mongodb.GridFSBucket (conn.db, opts);
});
});
}
util.inherits (GridFSController, BaseController);
/**
* Get the resource identifier.
*/
GridFSController.prototype.__defineGetter__ ('resourceId', function () {
return this._id;
});
/**
* Upload a new file to the database.
*
* @returns {*[]}
*/
GridFSController.prototype.create = function () {
var self = this;
return [
this._upload.single (this._name),
function (req, res) {
// Store the content type.
var opts = { contentType: req.file.mimetype};
// Include the user that uploaded the file.
var metadata = {};
if (self._resolveUser)
metadata.user = self._resolveUser (req);
if (metadata.length !== 0)
opts.metadata = metadata;
// Create a new upload stream for the file.
var uploadStream = self._bucket.openUploadStream (req.file.originalname, opts);
fs.createReadStream (req.file.path)
.pipe (uploadStream)
.once ('error', function (err) {
winston.log ('error', util.inspect (err));
res.status (500).json ({error: 'Upload failed'});
})
.once ('finish', function () {
res.status (200).json ({_id: uploadStream.id});
});
}
];
};
/**
* Disallow getting all the files. You can only get a single file at a time.
*
* @param opts
* @returns {Function}
*/
GridFSController.prototype.getAll = function () {
return function (req, res) {
return res.sendStatus (404);
}
};
/**
* Get a single file.
*
* @param opts
*/
GridFSController.prototype.get = function () {
var self = this;
return {
sanitize: function (req, callback) {
try {
var rcid = req.params[self._id];
req.params[self._id] = new mongodb.ObjectId (rcid);
return callback (null);
}
catch (e) {
return callback (new HttpError (404));
}
},
execute: function (req, res, callback) {
var id = req.params[self._id];
async.waterfall ([
function (callback) {
// Find information about the file.
var cursor = self._bucket.find ({_id: id});
return callback (null, cursor);
},
function (cursor, callback) {
cursor.next (function (err, item) {
// Make sure we close the cursor.
cursor.close ();
if (!item)
return callback (new HttpError (404, 'Resource does not exist'));
return callback (err, item)
});
},
function (file, callback) {
// Download the file.
var downloadStream = self._bucket.openDownloadStream (id);
res.type (file.contentType);
downloadStream
.pipe (res)
.once ('error', callback)
.once ('finish', callback);
}
], function (err) {
if (err && !(err instanceof HttpError))
err = new HttpError (500, 'Failed to retrieve file');
if (err)
return callback (err);
return callback (null);
});
}
};
};
/**
* Update a file.
*
* @returns {*[]}
*/
GridFSController.prototype.update = function () {
return function (req, res) {
res.sendStatus (404);
};
};
/**
* Delete a single file.
*
* @returns {Function}
*/
GridFSController.prototype.delete = function () {
var self = this;
return {
sanitize: function (req, callback) {
try {
var rcid = req.params[self._id];
req.params[self._id] = new mongodb.ObjectId (rcid);
return callback (null);
}
catch (e) {
return callback (new HttpError (404));
}
},
execute: function (req, res, callback) {
var id = req.params[self._id];
self._bucket.delete (id, function (err) {
if (err) return res.status (500).json ({errors: 'Delete operation failed'});
res.status (200).json (true);
return callback (null);
});
}
};
};
module.exports = exports = GridFSController;