|
'use strict'; |
|
const Busboy = require('busboy'); |
|
const uuidGen = require('uuid/v4'); |
|
const debug = require('debug')('upload'); |
|
|
|
module.exports = function(store) { |
|
if(typeof store.createWriteStream !== 'function') { |
|
// see https://github.com/maxogden/abstract-blob-store |
|
throw new Error('Store has to be an abstract-blob-store compatible Instance') |
|
} |
|
|
|
return function upload(req, res, next) { |
|
// Only for POST Requests of Type multipart/form-data |
|
if(req.method !== 'POST' || !req.headers['content-type'].startsWith('multipart/form-data')) { |
|
return next(); |
|
} |
|
debug('Received multipart/form-data POST on '+ req.url); |
|
|
|
req.body = { files: [] }; |
|
let uploading = 0, finished = false; |
|
const busboy = new Busboy({headers: req.headers}); |
|
|
|
function done() { |
|
// be sure busboy and every store-write is finished |
|
if(uploading > 0 || !finished) return; |
|
debug('Finished multipart/form-data POST on ' + req.url); |
|
next(); |
|
} |
|
|
|
// Listen for event when Busboy finds a file to stream. |
|
busboy.on('file', function(fieldname, stream, filename, encoding, mimetype) { |
|
debug('Uploading file ' + filename); |
|
uploading++; |
|
|
|
const meta = { |
|
key: uuidGen(), |
|
filename, |
|
mimetype |
|
}; |
|
|
|
const storeWS = store.createWriteStream(meta, function(err, data) { |
|
uploading--; |
|
if(err) return console.error(err); |
|
debug('Uploaded ' + filename); |
|
req.body.files.push(data); |
|
done(); |
|
}); |
|
|
|
// Pipe the file into store |
|
stream.pipe(storeWS); |
|
}); |
|
|
|
// adopt non file fields to body |
|
busboy.on('field', function(fieldname, val) { |
|
req.body[fieldname] = val; |
|
}); |
|
|
|
// Listen for event when Busboy is finished parsing the form |
|
busboy.on('finish', function() { |
|
finished = true; |
|
done(); |
|
}); |
|
|
|
// Pipe the HTTP Request into Busboy |
|
req.pipe(busboy); |
|
}; |
|
}; |