express-fileupload
Advanced tools
Comparing version 1.1.1-alpha.3 to 1.1.2-alpha.1
@@ -6,6 +6,65 @@ 'use strict'; | ||
const streamifier = require('streamifier'); | ||
const md5 = require('md5'); | ||
/** | ||
* Returns true if argument is function. | ||
*/ | ||
const isFunc = func => func && func.constructor && func.call && func.apply; | ||
/** | ||
* Creates a folder for file specified in the path variable | ||
* @param {Object} fileUploadOptions | ||
* @param {String} filePath | ||
*/ | ||
const checkAndMakeDir = function(fileUploadOptions, filePath){ | ||
if (fileUploadOptions && fileUploadOptions.createParentPath) { | ||
const parentPath = path.dirname(filePath); | ||
if (!fs.existsSync(parentPath)) { | ||
fs.mkdirSync(parentPath); | ||
} | ||
} | ||
}; | ||
/** | ||
* Returns Local function that moves the file to a different location on the filesystem | ||
* which takes two function arguments to make it compatible w/ Promise or Callback APIs | ||
* @param {String} filePath | ||
* @param {Object} options | ||
*/ | ||
const moveFromTemp = function(filePath, options) { | ||
return function(successFunc, errorFunc){ | ||
// Set errorFunc to the same value as successFunc for callback mode. | ||
errorFunc = isFunc(errorFunc) ? errorFunc : successFunc; | ||
fs.rename(options.tempFilePath, filePath, function(err){ | ||
if (err) { | ||
errorFunc(err); | ||
} else { | ||
successFunc(); | ||
} | ||
}); | ||
}; | ||
}; | ||
/** | ||
* Returns Local function that moves the file from buffer to a different location on the filesystem | ||
* which takes two function arguments to make it compatible w/ Promise or Callback APIs | ||
* @param {String} filePath | ||
* @param {Object} options | ||
*/ | ||
const moveFromBuffer = function(filePath, options) { | ||
return function(successFunc, errorFunc){ | ||
// Set errorFunc to the same value as successFunc for callback mode. | ||
errorFunc = isFunc(errorFunc) ? errorFunc : successFunc; | ||
const fstream = fs.createWriteStream(filePath); | ||
streamifier.createReadStream(options.buffer).pipe(fstream); | ||
fstream.on('error', function(error) { | ||
errorFunc(error); | ||
}); | ||
fstream.on('close', function() { | ||
successFunc(); | ||
}); | ||
}; | ||
}; | ||
module.exports = function(options, fileUploadOptions = null) { | ||
const output = { | ||
return { | ||
name: options.name, | ||
@@ -18,82 +77,16 @@ data: options.buffer, | ||
mimetype: options.mimetype, | ||
md5: () => md5(options.buffer), | ||
md5: options.hash, | ||
mv: function(filePath, callback) { | ||
// Callback is passed in, use the callback API | ||
if (callback) { | ||
if (options.buffer.length && !options.tempFilePath) { | ||
moveFromBuffer( | ||
() => { | ||
callback(null); | ||
}, | ||
error => { | ||
callback(error); | ||
} | ||
); | ||
} else { | ||
moveFromTemp( | ||
() => { | ||
callback(null); | ||
}, | ||
error => { | ||
callback(error); | ||
} | ||
); | ||
} | ||
// Otherwise, return a promise | ||
} else { | ||
return new Promise((resolve, reject) => { | ||
if (options.buffer) { | ||
moveFromBuffer(resolve, reject); | ||
} else { | ||
moveFromTemp(resolve, reject); | ||
} | ||
}); | ||
} | ||
function checkAndMakeDir(){ | ||
if (fileUploadOptions && fileUploadOptions.createParentPath) { | ||
const parentPath = path.dirname(filePath); | ||
if (!fs.existsSync(parentPath)) { | ||
fs.mkdirSync(parentPath); | ||
} | ||
} | ||
} | ||
/** | ||
* Local function that moves the file to a different location on the filesystem | ||
* Takes two function arguments to make it compatible w/ Promise or Callback APIs | ||
* @param {Function} successFunc | ||
* @param {Function} errorFunc | ||
*/ | ||
function moveFromTemp(successFunc, errorFunc) { | ||
checkAndMakeDir(); | ||
fs.rename(options.tempFilePath, filePath, function(err){ | ||
if (err) { | ||
errorFunc(err); | ||
} else { | ||
successFunc(); | ||
} | ||
}); | ||
} | ||
function moveFromBuffer(successFunc, errorFunc) { | ||
checkAndMakeDir(); | ||
const fstream = fs.createWriteStream(filePath); | ||
streamifier.createReadStream(options.buffer).pipe(fstream); | ||
fstream.on('error', function(error) { | ||
errorFunc(error); | ||
}); | ||
fstream.on('close', function() { | ||
successFunc(); | ||
}); | ||
} | ||
// Determine propper move function. | ||
let moveFunc = (options.buffer.length && !options.tempFilePath) | ||
? moveFromBuffer(filePath, options) | ||
: moveFromTemp(filePath, options); | ||
// Create a folder for file. | ||
checkAndMakeDir(fileUploadOptions, filePath); | ||
// If callback is passed in, use the callback API, otherwise return a promise. | ||
return isFunc(callback) | ||
? moveFunc(callback) | ||
: new Promise((resolve, reject) => moveFunc(resolve, reject)); | ||
} | ||
}; | ||
return output; | ||
}; |
@@ -0,1 +1,2 @@ | ||
const crypto = require('crypto'); | ||
@@ -11,2 +12,3 @@ /** | ||
let fileSize = 0; // eslint-disable-line | ||
let hash = crypto.createHash('md5'); | ||
@@ -16,2 +18,3 @@ return { | ||
buffers.push(data); | ||
hash.update(data); | ||
fileSize += data.length; | ||
@@ -31,2 +34,5 @@ if (options.debug) { | ||
}, | ||
getHash: function(){ | ||
return hash.digest('hex'); | ||
}, | ||
complete: function(){ | ||
@@ -33,0 +39,0 @@ return Buffer.concat(buffers); |
@@ -56,3 +56,3 @@ const Busboy = require('busboy'); | ||
const {dataHandler, getFilePath, getFileSize, complete, cleanup} = options.useTempFiles | ||
const {dataHandler, getFilePath, getFileSize, getHash, complete, cleanup} = options.useTempFiles | ||
? tempFileHandler(options, fieldname, filename) | ||
@@ -131,2 +131,3 @@ : memHandler(options, fieldname, filename); | ||
size: getFileSize(), | ||
hash: getHash(), | ||
encoding, | ||
@@ -133,0 +134,0 @@ truncated: file.truncated, |
const fs = require('fs'); | ||
const path = require('path'); | ||
const crypto = require('crypto'); | ||
module.exports = function(options, fieldname, filename) { | ||
const dir = path.normalize(options.tempFileDir || process.cwd() + '/tmp/'); | ||
let hash = crypto.createHash('md5'); | ||
@@ -17,2 +19,3 @@ if (!fs.existsSync(dir)) { | ||
writeStream.write(data); | ||
hash.update(data); | ||
fileSize += data.length; | ||
@@ -33,2 +36,10 @@ if (options.debug) { | ||
}, | ||
getHash: function(){ | ||
return hash.digest('hex'); | ||
}, | ||
complete: function(){ | ||
writeStream.end(); | ||
//return empty buffer since data has been uploaded to the temporary file. | ||
return Buffer.concat([]); | ||
}, | ||
cleanup: function(){ | ||
@@ -40,8 +51,4 @@ writeStream.end(); | ||
}); | ||
}, | ||
complete: function(){ | ||
writeStream.end(); | ||
return Buffer.concat([]); //return empty buffer since uploaded to the temporary file. | ||
} | ||
}; | ||
}; |
{ | ||
"name": "express-fileupload", | ||
"version": "1.1.1-alpha.3", | ||
"version": "1.1.2-alpha.1", | ||
"author": "Richard Girges <richardgirges@gmail.com>", | ||
@@ -14,3 +14,2 @@ "description": "Simple express file upload middleware that wraps around Busboy", | ||
"busboy": "^0.2.14", | ||
"md5": "^2.2.1", | ||
"streamifier": "^0.1.1" | ||
@@ -34,2 +33,3 @@ }, | ||
"devDependencies": { | ||
"md5": "^2.2.1", | ||
"body-parser": "^1.18.3", | ||
@@ -36,0 +36,0 @@ "coveralls": "^3.0.2", |
@@ -9,2 +9,7 @@ # express-fileupload | ||
# Version 1.1.1 Breaking Changes | ||
Breaking change to `md5` handling. | ||
md5 again returns a hash value instead of function which compute the hash. | ||
md5 hashes now can be used with tempFiles. | ||
# Version 1.0.0 Breaking Changes | ||
@@ -41,3 +46,4 @@ Breaking change to `md5` handling. [Read about it here.](https://github.com/richardgirges/express-fileupload/releases/tag/v1.0.0-alpha.1) | ||
* `req.files.foo.truncated`: A boolean that represents if the file is over the size limit | ||
* `req.files.foo.md5`: A function that returns an MD5 checksum of the uploaded file | ||
* `req.files.foo.size`: Uploaded size in bytes | ||
* `req.files.foo.md5`: MD5 checksum of the uploaded file | ||
@@ -60,3 +66,3 @@ ### Examples | ||
Use temp files instead of memory for managing the upload process. | ||
Please note: md5 hashes will not be generated when using tempFiles | ||
```javascript | ||
@@ -63,0 +69,0 @@ app.use(fileUpload({ |
@@ -12,2 +12,7 @@ 'use strict'; | ||
/** | ||
* Returns true if argument is function. | ||
*/ | ||
const isFunc = func => (func && func.constructor && func.call && func.apply) ? true : false; | ||
describe('Test of the fileFactory factory', function() { | ||
@@ -75,6 +80,13 @@ beforeEach(function() { | ||
name: 'basketball.png', | ||
buffer: mockBuffer, | ||
hash: mockMd5 | ||
}).md5, mockMd5); | ||
}); | ||
it('contains the mv method', function() { | ||
assert.equal(isFunc(fileFactory({ | ||
name: 'basketball.png', | ||
buffer: mockBuffer | ||
}).md5(), mockMd5); | ||
}).mv), true); | ||
}); | ||
}); | ||
}); |
'use strict'; | ||
const fs = require('fs'); | ||
const md5 = require('md5'); | ||
const path = require('path'); | ||
@@ -40,2 +41,5 @@ const request = require('supertest'); | ||
let filePath = path.join(fileDir, fileName); | ||
let fileBuffer = fs.readFileSync(filePath); | ||
let fileHash = md5(fileBuffer); | ||
let fileStat = fs.statSync(filePath); | ||
let uploadedFilePath = path.join(uploadDir, fileName); | ||
@@ -48,3 +52,13 @@ | ||
.attach('testFile', filePath) | ||
.expect(200) | ||
.expect((res)=>{ | ||
res.body.uploadDir = ''; | ||
res.body.uploadPath = ''; | ||
}) | ||
.expect(200, { | ||
name: fileName, | ||
md5: fileHash, | ||
size: fileStat.size, | ||
uploadDir: '', | ||
uploadPath: '' | ||
}) | ||
.end(function(err) { | ||
@@ -61,2 +75,5 @@ if (err) { | ||
let filePath = path.join(fileDir, fileName); | ||
let fileBuffer = fs.readFileSync(filePath); | ||
let fileHash = md5(fileBuffer); | ||
let fileStat = fs.statSync(filePath); | ||
let uploadedFilePath = path.join(uploadDir, fileName); | ||
@@ -69,3 +86,13 @@ | ||
.attach('testFile', filePath) | ||
.expect(200) | ||
.expect((res)=>{ | ||
res.body.uploadDir = ''; | ||
res.body.uploadPath = ''; | ||
}) | ||
.expect(200, { | ||
name: fileName, | ||
md5: fileHash, | ||
size: fileStat.size, | ||
uploadDir: '', | ||
uploadPath: '' | ||
}) | ||
.end(function(err) { | ||
@@ -115,2 +142,5 @@ if (err) { | ||
let filePath = path.join(fileDir, fileName); | ||
let fileBuffer = fs.readFileSync(filePath); | ||
let fileHash = md5(fileBuffer); | ||
let fileStat = fs.statSync(filePath); | ||
let uploadedFilePath = path.join(uploadDir, fileName); | ||
@@ -123,3 +153,13 @@ | ||
.attach('testFile', filePath) | ||
.expect(200) | ||
.expect((res)=>{ | ||
res.body.uploadDir = ''; | ||
res.body.uploadPath = ''; | ||
}) | ||
.expect(200, { | ||
name: fileName, | ||
md5: fileHash, | ||
size: fileStat.size, | ||
uploadDir: '', | ||
uploadPath: '' | ||
}) | ||
.end(function(err) { | ||
@@ -136,2 +176,5 @@ if (err) { | ||
let filePath = path.join(fileDir, fileName); | ||
let fileBuffer = fs.readFileSync(filePath); | ||
let fileHash = md5(fileBuffer); | ||
let fileStat = fs.statSync(filePath); | ||
let uploadedFilePath = path.join(uploadDir, fileName); | ||
@@ -144,3 +187,13 @@ | ||
.attach('testFile', filePath) | ||
.expect(200) | ||
.expect((res)=>{ | ||
res.body.uploadDir = ''; | ||
res.body.uploadPath = ''; | ||
}) | ||
.expect(200, { | ||
name: fileName, | ||
md5: fileHash, | ||
size: fileStat.size, | ||
uploadDir: '', | ||
uploadPath: '' | ||
}) | ||
.end(function(err) { | ||
@@ -186,14 +239,33 @@ if (err) { | ||
it('upload multiple files with POST', function(done) { | ||
let upload1 = path.join(fileDir, mockFiles[0]); | ||
let upload2 = path.join(fileDir, mockFiles[1]); | ||
let upload3 = path.join(fileDir, mockFiles[2]); | ||
let req = request(app).post('/upload/multiple'); | ||
clearUploadsDir(); | ||
request(app) | ||
.post('/upload/multiple') | ||
.attach('testFile1', upload1) | ||
.attach('testFile2', upload2) | ||
.attach('testFile3', upload3) | ||
.expect(200) | ||
let expectedResult = []; | ||
let expectedResultSorted = []; | ||
let uploadedFilesPath = []; | ||
mockFiles.forEach((fileName, index) => { | ||
let filePath = path.join(fileDir, fileName); | ||
let fileStat = fs.statSync(filePath); | ||
uploadedFilesPath.push(path.join(uploadDir, fileName)); | ||
expectedResult.push({ | ||
name:fileName, | ||
md5: md5(fs.readFileSync(filePath)), | ||
size: fileStat.size, | ||
uploadDir: '', | ||
uploadPath: '' | ||
}); | ||
req.attach(`testFile${index+1}`, filePath); | ||
}); | ||
req | ||
.expect((res)=>{ | ||
res.body.forEach(fileInfo => { | ||
fileInfo.uploadDir = ''; | ||
fileInfo.uploadPath = ''; | ||
let index = mockFiles.indexOf(fileInfo.name); | ||
expectedResultSorted.push(expectedResult[index]); | ||
}); | ||
}) | ||
.expect(200, expectedResultSorted) | ||
.end(function(err) { | ||
@@ -204,3 +276,3 @@ if (err) { | ||
fs.stat(upload1, function(err) { | ||
fs.stat(uploadedFilesPath[0], function(err) { | ||
if (err) { | ||
@@ -210,3 +282,3 @@ return done(err); | ||
fs.stat(upload2, function(err) { | ||
fs.stat(uploadedFilesPath[1], function(err) { | ||
if (err) { | ||
@@ -216,3 +288,3 @@ return done(err); | ||
fs.stat(upload3, done); | ||
fs.stat(uploadedFilesPath[2], done); | ||
}); | ||
@@ -230,8 +302,29 @@ }); | ||
for (let i = 0; i < mockFiles.length; i++) { | ||
req.attach('testFiles', path.join(fileDir, mockFiles[i])); | ||
} | ||
let expectedResult = []; | ||
let expectedResultSorted = []; | ||
let uploadedFilesPath = []; | ||
mockFiles.forEach((fileName) => { | ||
let filePath = path.join(fileDir, fileName); | ||
let fileStat = fs.statSync(filePath); | ||
uploadedFilesPath.push(path.join(uploadDir, fileName)); | ||
expectedResult.push({ | ||
name:fileName, | ||
md5: md5(fs.readFileSync(filePath)), | ||
size: fileStat.size, | ||
uploadDir: '', | ||
uploadPath: '' | ||
}); | ||
req.attach('testFiles', filePath); | ||
}); | ||
req | ||
.expect(200) | ||
.expect((res)=>{ | ||
res.body.forEach(fileInfo => { | ||
fileInfo.uploadDir = ''; | ||
fileInfo.uploadPath = ''; | ||
let index = mockFiles.indexOf(fileInfo.name); | ||
expectedResultSorted.push(expectedResult[index]); | ||
}); | ||
}) | ||
.expect(200, expectedResultSorted) | ||
.end(function(err) { | ||
@@ -242,5 +335,5 @@ if (err) { | ||
for (let i = 0; i < mockFiles.length; i++) { | ||
fs.statSync(path.join(uploadDir, mockFiles[i])); | ||
} | ||
uploadedFilesPath.forEach(function(uploadedFilePath){ | ||
fs.statSync(uploadedFilePath); | ||
}); | ||
@@ -258,2 +351,5 @@ done(); | ||
let filePath = path.join(fileDir, fileName); | ||
let fileBuffer = fs.readFileSync(filePath); | ||
let fileHash = md5(fileBuffer); | ||
let fileStat = fs.statSync(filePath); | ||
let uploadedFilePath = path.join(uploadDir, fileName); | ||
@@ -269,6 +365,15 @@ | ||
.field('email', mockUser.email) | ||
.expect((res)=>{ | ||
res.body.uploadDir = ''; | ||
res.body.uploadPath = ''; | ||
}) | ||
.expect(200, { | ||
firstName: mockUser.firstName, | ||
lastName: mockUser.lastName, | ||
email: mockUser.email | ||
email: mockUser.email, | ||
name: fileName, | ||
md5: fileHash, | ||
size: fileStat.size, | ||
uploadDir: '', | ||
uploadPath: '' | ||
}, | ||
@@ -286,2 +391,6 @@ function(err) { | ||
let filePath = path.join(fileDir, fileName); | ||
let fileBuffer = fs.readFileSync(filePath); | ||
let fileStat = fs.statSync(filePath); | ||
let fileHash = md5(fileBuffer); | ||
let uploadedFilePath = path.join(uploadDir, fileName); | ||
@@ -297,6 +406,15 @@ | ||
.field('email', mockUser.email) | ||
.expect((res)=>{ | ||
res.body.uploadDir = ''; | ||
res.body.uploadPath = ''; | ||
}) | ||
.expect(200, { | ||
firstName: mockUser.firstName, | ||
lastName: mockUser.lastName, | ||
email: mockUser.email | ||
email: mockUser.email, | ||
name: fileName, | ||
md5: fileHash, | ||
size: fileStat.size, | ||
uploadDir: '', | ||
uploadPath: '' | ||
}, | ||
@@ -303,0 +421,0 @@ function(err) { |
@@ -41,3 +41,10 @@ 'use strict'; | ||
res.send('File uploaded to ' + uploadPath); | ||
//res.send('File uploaded to ' + uploadPath); | ||
res.json({ | ||
name: testFile.name, | ||
uploadDir: uploadDir, | ||
uploadPath: uploadPath, | ||
md5: testFile.md5, | ||
size: testFile.size | ||
}); | ||
}); | ||
@@ -57,3 +64,9 @@ }); | ||
.then(() => { | ||
res.send('File uploaded to ' + uploadPath); | ||
res.json({ | ||
name: testFile.name, | ||
uploadDir: uploadDir, | ||
uploadPath: uploadPath, | ||
md5: testFile.md5, | ||
size: testFile.size | ||
}); | ||
}) | ||
@@ -97,3 +110,8 @@ .catch(err => { | ||
lastName: req.body.lastName, | ||
email: req.body.email | ||
email: req.body.email, | ||
name: testFile.name, | ||
uploadDir: uploadDir, | ||
uploadPath: uploadPath, | ||
md5: testFile.md5, | ||
size: testFile.size | ||
}); | ||
@@ -155,3 +173,26 @@ }); | ||
res.send('Files uploaded to ' + uploadDir); | ||
//res.send('Files uploaded to ' + uploadDir); | ||
res.json([ | ||
{ | ||
name: testFile1.name, | ||
uploadDir: uploadDir, | ||
uploadPath: uploadPath1, | ||
md5: testFile1.md5, | ||
size: testFile1.size | ||
}, | ||
{ | ||
name: testFile2.name, | ||
uploadDir: uploadDir, | ||
uploadPath: uploadPath2, | ||
md5: testFile2.md5, | ||
size: testFile2.size | ||
}, | ||
{ | ||
name: testFile2.name, | ||
uploadDir: uploadDir, | ||
uploadPath: uploadPath2, | ||
md5: testFile2.md5, | ||
size: testFile2.size | ||
} | ||
]); | ||
}); | ||
@@ -181,3 +222,3 @@ }); | ||
let filesUploaded = 0; | ||
let uploadResults = []; | ||
for (let i = 0; i < testFiles.length; i++) { | ||
@@ -191,4 +232,12 @@ let uploadPath = path.join(uploadDir, testFiles[i].name); | ||
if (++filesUploaded === testFiles.length) { | ||
res.send('File uploaded to ' + uploadPath); | ||
uploadResults.push({ | ||
name: testFiles[i].name, | ||
uploadDir: uploadDir, | ||
uploadPath: uploadPath, | ||
md5: testFiles[i].md5, | ||
size: testFiles[i].size | ||
}); | ||
if (uploadResults.length === testFiles.length) { | ||
res.json(uploadResults); | ||
} | ||
@@ -195,0 +244,0 @@ }); |
const fs = require('fs'); | ||
const md5 = require('md5'); | ||
const path = require('path'); | ||
@@ -29,2 +30,9 @@ const request = require('supertest'); | ||
) { | ||
let filePath = path.join(fileDir, actualFileNameToUpload); | ||
let fileBuffer = fs.readFileSync(filePath); | ||
let fileHash = md5(fileBuffer); | ||
let fileStat = fs.statSync(filePath); | ||
let uploadedFilePath = path.join(uploadDir, expectedFileNameOnFileSystem); | ||
request( | ||
@@ -34,10 +42,14 @@ server.setup(options) | ||
.post('/upload/single') | ||
.attach( | ||
'testFile', | ||
path.join( | ||
fileDir, | ||
actualFileNameToUpload | ||
) | ||
) | ||
.expect(200) | ||
.attach('testFile', filePath) | ||
.expect((res)=>{ | ||
res.body.uploadDir = ''; | ||
res.body.uploadPath = ''; | ||
}) | ||
.expect(200, { | ||
name: expectedFileNameOnFileSystem, | ||
md5: fileHash, | ||
size: fileStat.size, | ||
uploadDir: '', | ||
uploadPath: '' | ||
}) | ||
.end(function(err) { | ||
@@ -47,10 +59,4 @@ if (err) { | ||
} | ||
const uploadedFilePath = path.join( | ||
uploadDir, | ||
expectedFileNameOnFileSystem | ||
); | ||
fs.stat( | ||
uploadedFilePath, | ||
done | ||
); | ||
fs.stat(uploadedFilePath, done); | ||
}); | ||
@@ -57,0 +63,0 @@ } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1182530
2
1618
90
9
- Removedmd5@^2.2.1
- Removedcharenc@0.0.2(transitive)
- Removedcrypt@0.0.2(transitive)
- Removedis-buffer@1.1.6(transitive)
- Removedmd5@2.3.0(transitive)