imager
Version:
Easy way to resize, crop and upload images to Rackspace cloudfiles and Amazon S3
201 lines (174 loc) • 3.73 kB
JavaScript
;
/*!
* imager
* Copyright(c) 2014 Madhusudhan Srinivasa <madhums8@gmail.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var fs = require('fs');
var gm = require('graphicsmagick-stream');
var mime = require('mime');
var co = require('co');
var pkgcloud = require('pkgcloud');
var debug = require('debug')('imager');
/**
* Expose
*/
module.exports = Imager;
/**
* Imager
*
* @param {Object} presets
* @param {Object} storage
* @api public
*/
function Imager (presets, storage) {
if (!storage) {
storage = presets;
presets = {
original: {
original: true
}
};
}
this.client = pkgcloud.storage.createClient(storage);
this.presets = presets;
this.container = storage.container;
}
/**
* upload
*
* @param {Array|String} files
* @param {Function} fn
* @api public
*/
Imager.prototype.upload = function (files, fn) {
var self = this;
var presets = self.presets;
if (typeof files === 'string') files = [files];
presets = Object.keys(presets).map(function (key) {
presets[key].__name = key;
return presets[key];
});
co(function *() {
// modified files having the same object structure
var _files = yield files.map(info);
var arr = [];
_files.forEach(function (file) {
presets.forEach(function (preset) {
arr.push({ file: file, preset: preset });
});
});
try {
var uploaded = yield arr.map(upload.bind(self));
// group by preset
var hash = {};
for (var i = 0; i < uploaded.length; i++) {
var key = uploaded[i].preset;
if (!hash[key]) hash[key] = [];
hash[key].push(uploaded[i].url);
}
fn(null, hash);
} catch (err) {
fn(err);
}
})();
};
/**
* remove
*
* @param {Array|String} files
* @param {Function} fn
* @api public
*/
Imager.prototype.remove = function (files, fn) {
var self = this;
if (typeof files === 'string') files = [files];
co(function *() {
try {
yield files.map(remove.bind(self));
fn(null);
} catch (err) {
fn(err);
}
})();
};
/**
* upload
*
* @param {Object} file
* @api private
*/
function upload (obj) {
var container = this.container;
var client = this.client;
var preset = obj.preset;
var file = obj.file;
var filename = preset.rename && preset.rename(file);
return function (fn) {
var _convert = gm(preset.options);
var _upload = client.upload({
container: container,
remote: filename || (preset.__name + '_' + file.name)
}, done);
function done (err, uploaded, res) {
if (err) return fn(err);
fn(err, {
preset: preset.__name,
url: res.request.href
});
}
var stream = fs.createReadStream(file.path);
if (!preset.original) stream = stream.pipe(_convert());
stream.pipe(_upload);
};
}
/**
* remove
*
* @param {Object} file
* @api private
*/
function remove (file) {
var self = this;
return function (fn) {
self.client.removeFile(self.container, file, fn);
};
}
/**
* info
*
* @param {Object} file
* @return {Object}
* @api private
*/
function *info (file) {
return {
size: typeof(file) === 'string'
? (yield stat(file)).size
: file.size,
type: typeof(file) === 'string'
? mime.lookup(file)
: mime.lookup(file.path),
name: typeof(file) === 'string'
? file.split('/')[file.split('/').length - 1]
: file.originalname || file.name,
path: typeof(file) === 'string'
? file
: file.path
};
}
/**
* stat
*
* @param {String} path
* @return {Function}
* @api private
*/
function stat (path) {
return function (done) {
fs.stat(path, done);
};
}