Skip to content

Commit

Permalink
Merge pull request #65 from ShakMR/handle-file-limit
Browse files Browse the repository at this point in the history
Handle fileSize limit event with option
  • Loading branch information
richardgirges committed Jan 19, 2018
2 parents 4eaccda + a10fa54 commit bdfa47b
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 22 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ ehthumbs.db
Desktop.ini
.directory
*~
.idea
npm-debug.log
node_modules
*.log
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ The **req.files.foo** object will contain the following:
* `req.files.foo.mv`: A function to move the file elsewhere on your server
* `req.files.foo.mimetype`: The mimetype of your file
* `req.files.foo.data`: A buffer representation of your file
* `req.files.foo.truncated`: A boolean that represents if the file is over the size limit

### Full Example
**Your node.js code:**
Expand Down Expand Up @@ -120,6 +121,7 @@ Option | Acceptable Values | Details
--- | --- | ---
safeFileNames | <ul><li><code>false</code>&nbsp;**(default)**</li><li><code>true</code></li><li>regex</li></ul> | Strips characters from the upload's filename. You can use custom regex to determine what to strip. If set to `true`, non-alphanumeric characters _except_ dashes and underscores will be stripped. This option is off by default.<br /><br />**Example #1 (strip slashes from file names):** `app.use(fileUpload({ safeFileNames: /\\/g }))`<br />**Example #2:** `app.use(fileUpload({ safeFileNames: true }))`
preserveExtension | <ul><li><code>false</code>&nbsp;**(default)**</li><li><code>true</code></li><li><code>*Number*</code></li></ul> | Preserves filename extension when using <code>safeFileNames</code> option. If set to <code>true</code>, will default to an extension length of 3. If set to <code>*Number*</code>, this will be the max allowable extension length. If an extension is smaller than the extension length, it remains untouched. If the extension is longer, it is shifted.<br /><br />**Example #1 (true):**<br /><code>app.use(fileUpload({ safeFileNames: true, preserveExtension: true }));</code><br />*myFileName.ext* --> *myFileName.ext*<br /><br />**Example #2 (max extension length 2, extension shifted):**<br /><code>app.use(fileUpload({ safeFileNames: true, preserveExtension: 2 }));</code><br />*myFileName.ext* --> *myFileNamee.xt*
abortOnLimit | <ul><li><code>false</code>&nbsp;**(default)**</li><li><code>true</code></ul> | Returns a HTTP 413 when the file is bigger than the size limit if true. Otherwise, it will add a <code>truncate = true</code> to the resulting file structure.

# Help Wanted
Pull Requests are welcomed!
Expand Down
11 changes: 7 additions & 4 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,10 @@ function processMultipart(options, req, res, next) {
let safeFileNameRegex = /[^\w-]/g;

file.on('limit', () => {
res.writeHead(413, {'Connection': 'close'});
res.end('File size limit has been reached');
if (options.abortOnLimit) {
res.writeHead(413, {'Connection': 'close'});
res.end('File size limit has been reached');
}
});

file.on('data', function(data) {
Expand Down Expand Up @@ -139,6 +141,7 @@ function processMultipart(options, req, res, next) {
name: filename,
data: buf,
encoding: encoding,
truncated: file.truncated,
mimetype: mime,
md5: md5(buf),
mv: function(path, callback) {
Expand All @@ -163,8 +166,8 @@ function processMultipart(options, req, res, next) {
/**
* 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
* @param {Function} successFunc
* @param {Function} errorFunc
*/
function doMove(successFunc, errorFunc) {
const fstream = fs.createWriteStream(path);
Expand Down
66 changes: 48 additions & 18 deletions test/fileLimitUploads.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,65 @@

const path = require('path');
const request = require('supertest');
const assert = require('assert');
const server = require('./server');
const app = server.setup({
limits: {fileSize: 200 * 1024} // set 200kb upload limit
});
const clearUploadsDir = server.clearUploadsDir;
const fileDir = server.fileDir;

describe('Test Single File Upload With File Size Limit', function() {
it(`upload 'basketball.png' (~154kb) with 200kb size limit`, function(done) {
let filePath = path.join(fileDir, 'basketball.png');
let app;

beforeEach(function() {
clearUploadsDir();
});

describe('abort connection on limit reached', function() {
before(function() {
app = server.setup({
limits: {fileSize: 200 * 1024}, // set 200kb upload limit
abortOnLimit: true
});
});

it(`upload 'basketball.png' (~154kb) with 200kb size limit`, function(done) {
let filePath = path.join(fileDir, 'basketball.png');

request(app)
.post('/upload/single')
.attach('testFile', filePath)
.expect(200)
.end(done);
request(app)
.post('/upload/single/truncated')
.attach('testFile', filePath)
.expect(200)
.end(done);
});

it(`fail when uploading 'car.png' (~269kb) with 200kb size limit`, function(done) {
let filePath = path.join(fileDir, 'car.png');

request(app)
.post('/upload/single/truncated')
.attach('testFile', filePath)
.expect(413)
.end(done);
});
});

it(`fail when uploading 'car.png' (~269kb) with 200kb size limit`, function(done) {
let filePath = path.join(fileDir, 'car.png');
describe('pass truncated file to the next handler', function() {
before(function() {
app = server.setup({
limits: {fileSize: 200 * 1024} // set 200kb upload limit
});
});

clearUploadsDir();
it(`fail when uploading 'car.png' (~269kb) with 200kb size limit`, function(done) {
let filePath = path.join(fileDir, 'car.png');

request(app)
.post('/upload/single')
.attach('testFile', filePath)
.expect(413)
.end(done);
request(app)
.post('/upload/single/truncated')
.attach('testFile', filePath)
.expect(400)
.end(function(err, res) {
assert.ok(res.error.text === 'File too big');
done();
});
});
});
});
13 changes: 13 additions & 0 deletions test/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,19 @@ const setup = function(fileUploadOptions) {
});
});

app.all('/upload/single/truncated', function(req, res) {
if (!req.files) {
return res.status(400).send('No files were uploaded.');
}

if (req.files.testFile.truncated) {
// status 400 to differentiate from ending the request in the on limit
return res.status(400).send(`File too big`);
}

return res.status(200).send('Upload succeed');
});

app.all('/upload/multiple', function(req, res) {
if (!req.files) {
return res.status(400).send('No files were uploaded.');
Expand Down

0 comments on commit bdfa47b

Please sign in to comment.