Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

express-fileupload

Package Overview
Dependencies
Maintainers
1
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

express-fileupload - npm Package Compare versions

Comparing version 1.1.6-alpha.4 to 1.1.6-alpha.5

2

example/README.md

@@ -14,3 +14,3 @@ # express-fileupload Examples

app.post('/upload', function(req, res) {
if (Object.keys(req.files).length == 0) {
if (!req.files || Object.keys(req.files).length === 0) {
return res.status(400).send('No files were uploaded.');

@@ -17,0 +17,0 @@ }

@@ -19,3 +19,3 @@ const express = require('express');

if (Object.keys(req.files).length == 0) {
if (!req.files || Object.keys(req.files).length === 0) {
res.status(400).send('No files were uploaded.');

@@ -22,0 +22,0 @@ return;

@@ -5,5 +5,6 @@ 'use strict';

isFunc,
debugLog,
moveFile,
promiseCallback,
checkAndMakeDir,
moveFile,
saveBufferToFile

@@ -19,6 +20,5 @@ } = require('./utilities');

*/
const moveFromTemp = (filePath, options) => {
return (resolve, reject) => {
moveFile(options.tempFilePath, filePath, promiseCallback(resolve, reject));
};
const moveFromTemp = (filePath, options, fileUploadOptions) => (resolve, reject) => {
debugLog(fileUploadOptions, `Moving temporary file ${options.tempFilePath} to ${filePath}`);
moveFile(options.tempFilePath, filePath, promiseCallback(resolve, reject));
};

@@ -33,6 +33,5 @@

*/
const moveFromBuffer = (filePath, options) => {
return (resolve, reject) => {
saveBufferToFile(options.buffer, filePath, promiseCallback(resolve, reject));
};
const moveFromBuffer = (filePath, options, fileUploadOptions) => (resolve, reject) => {
debugLog(fileUploadOptions, `Moving uploaded buffer to ${filePath}`);
saveBufferToFile(options.buffer, filePath, promiseCallback(resolve, reject));
};

@@ -58,3 +57,3 @@

// Determine a propper move function.
let moveFunc = (options.buffer.length && !options.tempFilePath)
const moveFunc = (options.buffer.length && !options.tempFilePath)
? moveFromBuffer(filePath, options)

@@ -65,7 +64,5 @@ : moveFromTemp(filePath, options);

// If callback is passed in, use the callback API, otherwise return a promise.
return isFunc(callback)
? moveFunc(callback)
: new Promise(moveFunc);
return isFunc(callback) ? moveFunc(callback) : new Promise(moveFunc);
}
};
};

@@ -5,5 +5,5 @@ 'use strict';

const processNested = require('./processNested');
const {buildOptions} = require('./utilities');
const processMultipart = require('./processMultipart');
const isEligibleRequest = require('./isEligibleRequest');
const { buildOptions, debugLog } = require('./utilities');

@@ -35,3 +35,6 @@ const DEFAULT_OPTIONS = {

return (req, res, next) => {
if (!isEligibleRequest(req)) return next();
if (!isEligibleRequest(req)) {
debugLog(fileUploadOptions, 'Request is not eligible for file upload!');
return next();
}
processMultipart(fileUploadOptions, req, res, next);

@@ -38,0 +41,0 @@ };

@@ -9,4 +9,4 @@ const Busboy = require('busboy');

debugLog,
buildFields,
buildOptions,
buildFields,
parseFileName,

@@ -29,2 +29,6 @@ uriDecodeFileName

// Build busboy options and init busboy instance.
const busboyOptions = buildOptions(options, { headers: req.headers });
const busboy = new Busboy(busboyOptions);
// Close connection with specified reason and http code, default: 400 Bad Request.

@@ -37,27 +41,26 @@ const closeConnection = (code, reason) => {

// Build busboy options and init busboy instance.
let busboyOptions = buildOptions(options, {headers: req.headers});
let busboy = new Busboy(busboyOptions);
// Build multipart req.body fields
busboy.on('field', (fieldname, val) => req.body = buildFields(req.body, fieldname, val));
busboy.on('field', (field, val) => req.body = buildFields(req.body, field, val));
// Build req.files fields
busboy.on('file', (fieldname, file, name, encoding, mime) => {
busboy.on('file', (field, file, name, encoding, mime) => {
// Define upload timer settings
let uploadTimer = null;
const timeout = options.uploadTimeout;
// Decode file name if uriDecodeFileNames option set true.
const filename = uriDecodeFileName(options, name);
// Define methods and handlers for upload process.
const {dataHandler, getFilePath, getFileSize, getHash, complete, cleanup} = options.useTempFiles
? tempFileHandler(options, fieldname, filename)
: memHandler(options, fieldname, filename);
? tempFileHandler(options, field, filename) // Upload into temporary file.
: memHandler(options, field, filename); // Upload into RAM.
file.on('limit', () => {
debugLog(options, `Size limit reached for ${fieldname}->${filename}, bytes:${getFileSize()}`);
// Run user defined limit handler if it has been set.
if (isFunc(options.limitHandler)){
return options.limitHandler(req, res, next);
}
// Close connection with 413 code if abortOnLimit set(default: false).
debugLog(options, `Size limit reached for ${field}->${filename}, bytes:${getFileSize()}`);
// Reset upload timer in case of file limit reached.
clearTimeout(uploadTimer);
// Run a user defined limit handler if it has been set.
if (isFunc(options.limitHandler)) return options.limitHandler(req, res, next);
// Close connection with 413 code and do cleanup if abortOnLimit set(default: false).
if (options.abortOnLimit) {
debugLog(options, `Aborting upload because of size limit ${fieldname}->${filename}!`);
debugLog(options, `Aborting upload because of size limit ${field}->${filename}.`);
closeConnection(413, options.responseOnLimit);

@@ -68,27 +71,41 @@ cleanup();

file.on('data', dataHandler);
file.on('data', (data) => {
// Reset and set new upload timer each time when new data came.
clearTimeout(uploadTimer);
uploadTimer = setTimeout(() => {
debugLog(options, `Upload timeout ${field}->${filename}, bytes:${getFileSize()}`);
cleanup();
}, timeout);
// Handle new piece of data.
dataHandler(data);
});
file.on('end', () => {
// Debug logging for a new file upload.
debugLog(options, `Upload finished ${fieldname}->${filename}, bytes:${getFileSize()}`);
debugLog(options, `Upload finished ${field}->${filename}, bytes:${getFileSize()}`);
// Reset upload timer in case of end event.
clearTimeout(uploadTimer);
// Add file instance to the req.files
req.files = buildFields(req.files, fieldname, fileFactory(
{
buffer: complete(),
name: parseFileName(options, filename),
tempFilePath: getFilePath(),
size: getFileSize(),
hash: getHash(),
encoding,
truncated: file.truncated,
mimetype: mime
},
options
));
req.files = buildFields(req.files, field, fileFactory({
buffer: complete(),
name: parseFileName(options, filename),
tempFilePath: getFilePath(),
size: getFileSize(),
hash: getHash(),
encoding,
truncated: file.truncated,
mimetype: mime
}, options));
});
file.on('error', cleanup, next);
file.on('error', (err) => {
// Reset upload timer in case of errors.
clearTimeout(uploadTimer);
debugLog(options, `Error ${field}->${filename}, bytes:${getFileSize()}, error:${err}`);
cleanup();
next();
});
// Debug logging for a new file upload.
debugLog(options, `New upload started ${fieldname}->${filename}, bytes:${getFileSize()}`);
debugLog(options, `New upload started ${field}->${filename}, bytes:${getFileSize()}`);
});

@@ -95,0 +112,0 @@

@@ -7,3 +7,4 @@ const fs = require('fs');

checkAndMakeDir,
getTempFilename
getTempFilename,
deleteFile
} = require('./utilities');

@@ -14,7 +15,8 @@

const tempFilePath = path.join(dir, getTempFilename());
checkAndMakeDir({createParentPath: true}, tempFilePath);
let hash = crypto.createHash('md5');
let writeStream = fs.createWriteStream(tempFilePath);
debugLog(options, `Temporary file path is ${tempFilePath}`);
const hash = crypto.createHash('md5');
const writeStream = fs.createWriteStream(tempFilePath);
let fileSize = 0; // eslint-disable-line

@@ -27,3 +29,3 @@

fileSize += data.length;
debugLog(options, `Uploading ${fieldname} -> ${filename}, bytes: ${fileSize}`);
debugLog(options, `Uploading ${fieldname}->${filename}, bytes:${fileSize}...`);
},

@@ -35,12 +37,11 @@ getFilePath: () => tempFilePath,

writeStream.end();
//return empty buffer since data uploaded to the temporary file.
// Return empty buff since data was uploaded into a temp file.
return Buffer.concat([]);
},
cleanup: () => {
debugLog(options, `Cleaning up temporary file ${tempFilePath}...`);
writeStream.end();
fs.unlink(tempFilePath, (err) => {
if (err) throw err;
});
deleteFile(tempFilePath, (err) => { if (err) throw err; });
}
};
};
{
"name": "express-fileupload",
"version": "1.1.6-alpha.4",
"version": "1.1.6-alpha.5",
"author": "Richard Girges <richardgirges@gmail.com>",

@@ -5,0 +5,0 @@ "description": "Simple express file upload middleware that wraps around Busboy",

@@ -12,2 +12,3 @@ 'use strict';

const uploadDir = server.uploadDir;
const clearTempDir = server.clearTempDir;
const clearUploadsDir = server.clearUploadsDir;

@@ -276,3 +277,3 @@

it('fail when no files were attached', function(done) {
it('fail when no files were attached', (done) => {
request(app)

@@ -284,3 +285,3 @@ .post('/upload/single')

it('fail when using GET', function(done) {
it('fail when using GET', (done) => {
request(app)

@@ -293,3 +294,3 @@ .get('/upload/single')

it('fail when using HEAD', function(done) {
it('fail when using HEAD', (done) => {
request(app)

@@ -306,20 +307,13 @@ .head('/upload/single')

it('upload multiple files with POST', function(done) {
it('upload multiple files with POST', (done) => {
clearUploadsDir();
const req = request(app).post('/upload/multiple');
let expectedResult = [];
let expectedResultSorted = [];
let uploadedFilesPath = [];
const expectedResult = [];
const expectedResultSorted = [];
const uploadedFilesPath = [];
mockFiles.forEach((fileName, index) => {
let filePath = path.join(fileDir, fileName);
let fileStat = fs.statSync(filePath);
const filePath = path.join(fileDir, fileName);
req.attach(`testFile${index + 1}`, 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);
expectedResult.push(genUploadResult(fileName, filePath));
});

@@ -329,6 +323,6 @@

.expect((res) => {
res.body.forEach(fileInfo => {
res.body.forEach((fileInfo) => {
fileInfo.uploadDir = '';
fileInfo.uploadPath = '';
let index = mockFiles.indexOf(fileInfo.name);
const index = mockFiles.indexOf(fileInfo.name);
expectedResultSorted.push(expectedResult[index]);

@@ -342,3 +336,3 @@ });

if (err) return done(err);
fs.stat(uploadedFilesPath[1], function(err) {
fs.stat(uploadedFilesPath[1], (err) => {
if (err) return done(err);

@@ -355,19 +349,12 @@ fs.stat(uploadedFilesPath[2], done);

it('upload array of files with POST', function(done) {
it('upload array of files with POST', (done) => {
clearUploadsDir();
const req = request(app).post('/upload/array');
let expectedResult = [];
let expectedResultSorted = [];
let uploadedFilesPath = [];
const expectedResult = [];
const expectedResultSorted = [];
const uploadedFilesPath = [];
mockFiles.forEach((fileName) => {
let filePath = path.join(fileDir, fileName);
let fileStat = fs.statSync(filePath);
const filePath = path.join(fileDir, fileName);
uploadedFilesPath.push(path.join(uploadDir, fileName));
expectedResult.push({
name:fileName,
md5: md5(fs.readFileSync(filePath)),
size: fileStat.size,
uploadDir: '',
uploadPath: ''
});
expectedResult.push(genUploadResult(fileName, filePath));
req.attach('testFiles', filePath);

@@ -378,6 +365,6 @@ });

.expect((res)=>{
res.body.forEach(fileInfo => {
res.body.forEach((fileInfo) => {
fileInfo.uploadDir = '';
fileInfo.uploadPath = '';
let index = mockFiles.indexOf(fileInfo.name);
const index = mockFiles.indexOf(fileInfo.name);
expectedResultSorted.push(expectedResult[index]);

@@ -433,1 +420,42 @@ });

});
describe('Test Aborting/Canceling during upload', function() {
this.timeout(4000); // Set timeout for async tests.
const uploadTimeout = 1000;
const app = server.setup({
useTempFiles: true,
tempFileDir: tempDir,
debug: true,
uploadTimeout
});
clearTempDir();
clearUploadsDir();
mockFiles.forEach((fileName) => {
const filePath = path.join(fileDir, fileName);
it(`Delete temp file if ${fileName} upload was aborted`, (done) => {
const req = request(app)
.post('/upload/single')
.attach('testFile', filePath)
.on('progress', (e) => {
const progress = (e.loaded * 100) / e.total;
// Aborting request, use req.req since it is original superagent request.
if (progress > 50) req.req.abort();
})
.end((err) => {
if (!err) return done(`Connection hasn't been aborted!`);
if (err.code !== 'ECONNRESET') return done(err);
// err.code === 'ECONNRESET' that means upload has been aborted.
// Checking temp directory after upload timeout.
setTimeout(() => {
fs.readdir(tempDir, (err, files) => {
if (err) return done(err);
return files.length ? done(`Temporary directory contains files!`) : done();
});
}, uploadTimeout * 2);
});
});
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc