Skip to content

Commit a10fa54

Browse files
committed
Adding option to select between two behaviour when file over fileSize
1 parent 1c52f44 commit a10fa54

File tree

5 files changed

+71
-22
lines changed

5 files changed

+71
-22
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ ehthumbs.db
66
Desktop.ini
77
.directory
88
*~
9+
.idea
910
npm-debug.log
1011
node_modules
1112
*.log

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ The **req.files.foo** object will contain the following:
4040
* `req.files.foo.mv`: A function to move the file elsewhere on your server
4141
* `req.files.foo.mimetype`: The mimetype of your file
4242
* `req.files.foo.data`: A buffer representation of your file
43+
* `req.files.foo.truncated`: A boolean that represents if the file is over the size limit
4344

4445
### Full Example
4546
**Your node.js code:**
@@ -120,6 +121,7 @@ Option | Acceptable Values | Details
120121
--- | --- | ---
121122
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 }))`
122123
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*
124+
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.
123125

124126
# Help Wanted
125127
Pull Requests are welcomed!

lib/index.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,10 @@ function processMultipart(options, req, res, next) {
7474
let safeFileNameRegex = /[^\w-]/g;
7575

7676
file.on('limit', () => {
77-
res.writeHead(413, {'Connection': 'close'});
78-
res.end('File size limit has been reached');
77+
if (options.abortOnLimit) {
78+
res.writeHead(413, {'Connection': 'close'});
79+
res.end('File size limit has been reached');
80+
}
7981
});
8082

8183
file.on('data', function(data) {
@@ -138,6 +140,7 @@ function processMultipart(options, req, res, next) {
138140
name: filename,
139141
data: buf,
140142
encoding: encoding,
143+
truncated: file.truncated,
141144
mimetype: mime,
142145
mv: function(path, callback) {
143146
// Callback is passed in, use the callback API
@@ -161,8 +164,8 @@ function processMultipart(options, req, res, next) {
161164
/**
162165
* Local function that moves the file to a different location on the filesystem
163166
* Takes two function arguments to make it compatible w/ Promise or Callback APIs
164-
* @param {Function} successFunc
165-
* @param {Function} errorFunc
167+
* @param {Function} successFunc
168+
* @param {Function} errorFunc
166169
*/
167170
function doMove(successFunc, errorFunc) {
168171
const fstream = fs.createWriteStream(path);

test/fileLimitUploads.spec.js

+48-18
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,65 @@
22

33
const path = require('path');
44
const request = require('supertest');
5+
const assert = require('assert');
56
const server = require('./server');
6-
const app = server.setup({
7-
limits: {fileSize: 200 * 1024} // set 200kb upload limit
8-
});
97
const clearUploadsDir = server.clearUploadsDir;
108
const fileDir = server.fileDir;
119

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

13+
beforeEach(function() {
1614
clearUploadsDir();
15+
});
16+
17+
describe('abort connection on limit reached', function() {
18+
before(function() {
19+
app = server.setup({
20+
limits: {fileSize: 200 * 1024}, // set 200kb upload limit
21+
abortOnLimit: true
22+
});
23+
});
24+
25+
it(`upload 'basketball.png' (~154kb) with 200kb size limit`, function(done) {
26+
let filePath = path.join(fileDir, 'basketball.png');
1727

18-
request(app)
19-
.post('/upload/single')
20-
.attach('testFile', filePath)
21-
.expect(200)
22-
.end(done);
28+
request(app)
29+
.post('/upload/single/truncated')
30+
.attach('testFile', filePath)
31+
.expect(200)
32+
.end(done);
33+
});
34+
35+
it(`fail when uploading 'car.png' (~269kb) with 200kb size limit`, function(done) {
36+
let filePath = path.join(fileDir, 'car.png');
37+
38+
request(app)
39+
.post('/upload/single/truncated')
40+
.attach('testFile', filePath)
41+
.expect(413)
42+
.end(done);
43+
});
2344
});
2445

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

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

30-
request(app)
31-
.post('/upload/single')
32-
.attach('testFile', filePath)
33-
.expect(413)
34-
.end(done);
56+
request(app)
57+
.post('/upload/single/truncated')
58+
.attach('testFile', filePath)
59+
.expect(400)
60+
.end(function(err, res) {
61+
assert.ok(res.error.text === 'File too big');
62+
done();
63+
});
64+
});
3565
});
3666
});

test/server.js

+13
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,19 @@ const setup = function(fileUploadOptions) {
9292
});
9393
});
9494

95+
app.all('/upload/single/truncated', function(req, res) {
96+
if (!req.files) {
97+
return res.status(400).send('No files were uploaded.');
98+
}
99+
100+
if (req.files.testFile.truncated) {
101+
// status 400 to differentiate from ending the request in the on limit
102+
return res.status(400).send(`File too big`);
103+
}
104+
105+
return res.status(200).send('Upload succeed');
106+
});
107+
95108
app.all('/upload/multiple', function(req, res) {
96109
if (!req.files) {
97110
return res.status(400).send('No files were uploaded.');

0 commit comments

Comments
 (0)