Skip to content

Instantly share code, notes, and snippets.

@der-On
Created May 14, 2013 22:48
Show Gist options
  • Save der-On/5580296 to your computer and use it in GitHub Desktop.
Save der-On/5580296 to your computer and use it in GitHub Desktop.
node.js uploader based on "formidable"
var formidable = require('formidable');
var path = require('path');
var fs = require('fs');
var UploaderException = function(message)
{
this.message = message;
this.toString = function()
{
return 'Uploader error: '+this.message;
}
}
/**
* @class Uploader
* @static
*/
var Uploader = {
MSG_ERROR_NO_FIELD_NAME: 'Missing option "fieldNames".',
MSG_ERROR_NO_FIELE_NAMES: 'Option keepFileNames is set to false, but no fileNames are given.',
MSG_ERROR_NO_DEST: 'Missing option "dest".',
MSG_ERROR_WRONG_METHDO: 'Request method is not POST',
/**
* @method upload
* @param {Http.ServerRequest} req
* @param {Object} options
* @param {Function} callback(err, {Array} fields, {Array} files)
*
* Available options:
*
* - tempDir: (default=false) temp directory for uploads, if false the systems temp dir will be used
* - dest: Destination directory for the uploaded files.
* - fieldNames: Array of file field names in the form to upload
* - keepFileNames: (default=true) true | false, if true will keep the original file names, if false you must specifify the fileNames
* - fileNames: (default=null) Array of new file names for the uploaded files. Use the same order as in fieldNames.
*/
upload: function(req, options, callback)
{
var self = this;
var err = false;
var files = [];
var valid = true;
var options = {
tempDir: options.tempDir || false, // temp directory for uploads
fieldNames: options.fieldNames || null, // names of the file fields in the form
keepFileNames: options.keepFileNames || true, // keep the original file name
fileNames: options.fileNames || null, // if keepFilename = false, provide new file names
dest: options.dest || null, // destination directory where to move the uploaded file,
validator: options.validator || null // a file validation function that gets called for each file and must return true if the file passes validation and should be uploaded or false if not.
};
if (!options.fieldNames) err = new UploaderException(Uploader.MSG_ERROR_NO_FIELD_NAME);
if (!options.dest) err = new UploaderException(Uploader.MSG_ERROR_NO_DEST);
if (!options.keepFileNames && !options.fileNames) err = new new UploaderException(Uploader.MSG_ERROR_NO_FILE_NAMES);
if (req.method.toLowerCase() != 'post') err = new UploaderException(Uploader.MSG_ERROR_WRONG_METHOD);
if (!err) {
req.pause();
req.resume();
var formOpts = {
keepExtensions: true
};
if (options.tempDir) {
formOpts.uploadDir = options.tempDir;
}
var form = new formidable.IncomingForm(formOpts);
form.parse(req,function onFormParsed(formErr, formFields, formFiles) {
if (err) {
if (callback) callback(err, null, null);
} else {
options.fieldNames.forEach(function processFileFields(fieldName,i){
if (fieldName in formFiles && formFiles[fieldName].path && formFiles[fieldName].name != null && formFiles[fieldName].name != '') {
var formFile = formFiles[fieldName];
if (typeof options.validator == 'function') {
valid = options.validator(formFile);
} else {
valid = true;
}
if (valid) {
var fileName = (options.keepFileNames) ? formFile.name : options.fileNames[i];
var filePath = path.join(options.dest,fileName);
self.moveUploadedFile(formFile.path, filePath);
files.push(filePath);
}
}
});
if (callback) callback(false, formFields, files);
}
});
} else {
if (callback) callback(err, null, null);
}
},
moveUploadedFile: function(src,dest)
{
var dir = path.dirname(dest);
// create directory if not existing yet
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir,0755);
}
fs.renameSync(src,dest);
}
};
module.exports = Uploader;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment