dcms
Version:
CMS library for Node.js
206 lines (181 loc) • 7.71 kB
JavaScript
var EventEmitter = require('events').EventEmitter,
path = require('path'),
fs = require('fs'),
formidable = require('formidable'),
imageMagick = require('imagemagick'),
mkdirp = require('mkdirp'),
_ = require('lodash');
module.exports = function (options) {
var FileInfo = require('./fileinfo')(
_.extend({
baseDir: options.uploadDir
}, _.pick(options, 'minFileSize', 'maxFileSize', 'acceptFileTypes'))
);
var UploadHandler = function (req, res, callback) {
EventEmitter.call(this);
this.req = req;
this.res = res;
this.callback = callback;
};
require('util').inherits(UploadHandler, EventEmitter);
UploadHandler.prototype.noCache = function () {
this.res.set({
'Pragma': 'no-cache',
'Cache-Control': 'no-store, no-cache, must-revalidate',
'Content-Disposition': 'inline; filename="files.json"'
});
};
UploadHandler.prototype.get = function () {
this.noCache();
var files = [];
fs.readdir(options.uploadDir(), _.bind(function (err, list) {
_.each(list, function (name) {
var stats = fs.statSync(options.uploadDir() + '/' + name),
fileInfo;
if (stats.isFile()) {
fileInfo = new FileInfo({
name: name,
size: stats.size
});
this.initUrls(fileInfo);
files.push(fileInfo);
}
}, this);
this.callback(files);
}, this));
};
UploadHandler.prototype.post = function () {
var self = this,
form = new formidable.IncomingForm(),
tmpFiles = [],
files = [],
map = {},
counter = 1,
redirect,
finish = _.bind(function (werr) {
if(werr) console.warn(werr);
if (!--counter) {
_.each(files, function (fileInfo) {
this.initUrls(fileInfo);
this.emit('end', fileInfo);
}, this);
this.callback(files, redirect);
}
}, this);
this.noCache();
form.uploadDir = options.tmpDir;
form
.on('fileBegin', function (name, file) {
tmpFiles.push(file.path);
file.name = options.fileName(file.name, file);
var fileInfo = new FileInfo(file);
fileInfo.safeName();
map[path.basename(file.path)] = fileInfo;
files.push(fileInfo);
self.emit('begin', fileInfo);
})
.on('field', function (name, value) {
if (name === 'redirect') {
redirect = value;
}
})
.on('file', function (name, file) {
var fileInfo = map[path.basename(file.path)];
if (fs.existsSync(file.path)) {
fileInfo.size = file.size;
if (!fileInfo.validate()) {
fs.unlink(file.path);
return;
}
var generatePreviews = function () {
if (options.imageTypes.test(fileInfo.name)) {
_.each(options.imageVersions, function (value, version) {
// creating directory recursive
if (!fs.existsSync(options.uploadDir() + '/' + version + '/'))
mkdirp.sync(options.uploadDir() + '/' + version + '/');
counter++;
var opts = options.imageVersions[version];
imageMagick.resize(_.extend({
// quality: 1,
srcPath: options.uploadDir() + '/' + fileInfo.name,
dstPath: options.uploadDir() + '/' + version + '/' + fileInfo.name,
customArgs: opts.imageArgs || ['-auto-orient']
}, opts), finish);
});
if(options.imageResize) {
counter++;
imageMagick.resize(_.extend({
// quality: 1,
srcPath: options.uploadDir() + '/' + fileInfo.name,
dstPath: options.uploadDir() + '/' + fileInfo.name,
customArgs: options.imageResize.imageArgs || ['-auto-orient']
}, options.imageResize), finish);
}
}
}
if (!fs.existsSync(options.uploadDir() + '/'))
mkdirp.sync(options.uploadDir() + '/');
counter++;
fs.rename(file.path, options.uploadDir() + '/' + fileInfo.name, function (err) {
if (!err) {
generatePreviews();
finish();
} else {
var is = fs.createReadStream(file.path);
var os = fs.createWriteStream(options.uploadDir() + '/' + fileInfo.name);
is.on('end', function (err) {
if (!err) {
fs.unlinkSync(file.path);
generatePreviews();
}
finish();
});
is.pipe(os);
}
});
}
})
.on('aborted', function () {
_.each(tmpFiles, function (file) {
var fileInfo = map[path.basename(file)];
self.emit('abort', fileInfo);
fs.unlink(file);
});
})
.on('error', function (e) {
self.emit('error', e);
})
.on('progress', function (bytesReceived, bytesExpected) {
if (bytesReceived > options.maxPostSize)
self.req.connection.destroy();
})
.on('end', finish)
.parse(self.req);
};
UploadHandler.prototype.destroy = function () {
var self = this,
fileName = path.basename(decodeURIComponent(this.req.url));
fs.exists(options.uploadDir() + '/' + fileName, function(ex) {
if(!ex)
return self.callback(!ex);
fs.unlink(options.uploadDir() + '/' + fileName, function (err) {
_.each(options.imageVersions, function (value, version) {
fs.unlink(options.uploadDir() + '/' + version + '/' + fileName);
});
self.emit('delete', fileName);
self.callback(!err);
});
});
};
UploadHandler.prototype.initUrls = function (fileInfo) {
var baseUrl = options.hostname ? (options.ssl ? 'https:' : 'http:') + '//' + options.hostname : '';
fileInfo.setUrl(null, baseUrl + options.uploadUrl());
fileInfo.setUrl('delete', baseUrl + this.req.originalUrl);
_.each(options.imageVersions, function (value, version) {
if (fs.existsSync(options.uploadDir() + '/' + version + '/' + fileInfo.name)) {
fileInfo.setUrl(version, baseUrl + options.uploadUrl() + '/' + version);
}
}, this);
};
return UploadHandler;
};