done purchases remove, ocr scan, read image

This commit is contained in:
LukasNowy
2019-01-28 01:34:06 +01:00
parent d9c3d422d7
commit 93bbf9c2cb
203 changed files with 21267 additions and 41 deletions

View File

@ -0,0 +1 @@
coverage

View File

@ -0,0 +1,23 @@
{
"extends": [
"eslint:recommended"
],
"env": {
"node": true,
"mocha": true,
"es6": true
},
"parserOptions": {
"ecmaVersion": 6
},
"rules": {
"comma-dangle": [2, "never"],
"max-len": [2, {
"code": 100,
"tabWidth": 2
}],
"semi": 2,
"keyword-spacing": 2,
"indent": [2, 2, { "SwitchCase": 1 }]
}
}

View File

@ -0,0 +1 @@
{singleQuote: true}

View File

@ -0,0 +1,14 @@
language: node_js
node_js:
- "6"
- "7"
- "8"
- "9"
- "10"
env:
- COVERALLS_REPO_TOKEN=vNV8IQ0jJAuWGikebCeIHJryRulP6aEHa
script:
- npm run lint
- npm test
- npm run coveralls
after_success: 'npm run coveralls'

22
express-server/node_modules/express-fileupload/LICENSE generated vendored Normal file
View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Richard Girges
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,83 @@
# express-fileupload
Simple express middleware for uploading files.
[![npm](https://img.shields.io/npm/v/express-fileupload.svg)](https://www.npmjs.org/package/express-fileupload)
[![Build Status](https://travis-ci.org/richardgirges/express-fileupload.svg?branch=master)](https://travis-ci.org/richardgirges/express-fileupload)
[![downloads per month](http://img.shields.io/npm/dm/express-fileupload.svg)](https://www.npmjs.org/package/express-fileupload)
[![Coverage Status](https://img.shields.io/coveralls/richardgirges/express-fileupload.svg)](https://coveralls.io/r/richardgirges/express-fileupload)
# Version 1.0.0 Breaking Changes
Breaking change to `md5` handling. [Read about it here.](https://github.com/richardgirges/express-fileupload/releases/tag/v1.0.0-alpha.1)
# Install
```bash
# With NPM
npm install --save express-fileupload
# With Yarn
yarn add express-fileupload
```
# Usage
When you upload a file, the file will be accessible from `req.files`.
Example:
* You're uploading a file called **car.jpg**
* Your input's name field is **foo**: `<input name="foo" type="file" />`
* In your express server request, you can access your uploaded file from `req.files.foo`:
```javascript
app.post('/upload', function(req, res) {
console.log(req.files.foo); // the uploaded file object
});
```
The **req.files.foo** object will contain the following:
* `req.files.foo.name`: "car.jpg"
* `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
* `req.files.foo.md5`: A function that returns an MD5 checksum of the uploaded file
### Examples
* [Example Project](https://github.com/richardgirges/express-fileupload/tree/master/example)
* [Basic File Upload](https://github.com/richardgirges/express-fileupload/tree/master/example#basic-file-upload)
* [Multi-File Upload](https://github.com/richardgirges/express-fileupload/tree/master/example#multi-file-upload)
### Using Busboy Options
Pass in Busboy options directly to the express-fileupload middleware. [Check out the Busboy documentation here.](https://github.com/mscdex/busboy#api)
```javascript
app.use(fileUpload({
limits: { fileSize: 50 * 1024 * 1024 },
}));
```
### Using useTempFile Options
Use temp files instead of memory for managing the upload process.
Please note: md5 hashes will not be generated when using tempFiles
```javascript
app.use(fileUpload({
useTempFiles : true,
tempFileDir : '/tmp/'
}));
```
### Available Options
Pass in non-Busboy options directly to the middleware. These are express-fileupload specific options.
Option | Acceptable&nbsp;Values | Details
--- | --- | ---
createParentPath | <ul><li><code>false</code>&nbsp;**(default)**</li><li><code>true</code></ul> | Automatically creates the directory path specified in `.mv(filePathName)`
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.
useTempFiles | <ul><li><code>false</code>&nbsp;**(default)**</li><li><code>true</code></ul> | Will use temporary files at the specified tempDir for managing uploads rather than using buffers in memory. This avoids memory issues when uploading large files.
tempFileDir | <ul><li><code>String</code>&nbsp;**(path)**</li></ul> | Used with the <code>useTempFiles</code> option. Path to the directory where temp files will be stored during the upload process. Add trailing slash.
parseNested | <ul><li><code>false</code>&nbsp;**(default)**</li><li><code>true</code></li></ul> | By default, req.body and req.files are flattened like this: <code>{'name': 'John', 'hobbies[0]': 'Cinema', 'hobbies[1]': 'Bike'}</code><br /><br/>When this option is enabled they are parsed in order to be nested like this: <code>{'name': 'John', 'hobbies': ['Cinema', 'Bike']}</code>
# Help Wanted
Looking for additional maintainers. Please contact `richardgirges [ at ] gmail.com` if you're interested. Pull Requests are welcomed!
# Thanks & Credit
[Brian White](https://github.com/mscdex) for his stellar work on the [Busboy Package](https://github.com/mscdex/busboy) and the [connect-busboy Package](https://github.com/mscdex/connect-busboy)

View File

@ -0,0 +1,66 @@
# express-fileupload Examples
## Basic File Upload
**Your node.js code:**
```javascript
const express = require('express');
const fileUpload = require('express-fileupload');
const app = express();
// default options
app.use(fileUpload());
app.post('/upload', function(req, res) {
if (Object.keys(req.files).length == 0) {
return res.status(400).send('No files were uploaded.');
}
// The name of the input field (i.e. "sampleFile") is used to retrieve the uploaded file
let sampleFile = req.files.sampleFile;
// Use the mv() method to place the file somewhere on your server
sampleFile.mv('/somewhere/on/your/server/filename.jpg', function(err) {
if (err)
return res.status(500).send(err);
res.send('File uploaded!');
});
});
```
**Your HTML file upload form:**
```html
<html>
<body>
<form ref='uploadForm'
id='uploadForm'
action='http://localhost:8000/upload'
method='post'
encType="multipart/form-data">
<input type="file" name="sampleFile" />
<input type='submit' value='Upload!' />
</form>
</body>
</html>
```
## Multi-File Upload
express-fileupload supports multiple file uploads at the same time.
Let's say you have three files in your form, each of the inputs with the name `my_profile_pic`, `my_pet`, and `my_cover_photo`:
```html
<input type="file" name="my_profile_pic" />
<input type="file" name="my_pet" />
<input type="file" name="my_cover_photo" />
```
These uploaded files would be accessible like so:
```javascript
app.post('/upload', function(req, res) {
// Uploaded files:
console.log(req.files.my_profile_pic.name);
console.log(req.files.my_pet.name);
console.log(req.files.my_cover_photo.name);
});
```

View File

@ -0,0 +1,12 @@
<html>
<body>
<form ref='uploadForm'
id='uploadForm'
action='/upload'
method='post'
encType="multipart/form-data">
<input type="file" name="sampleFile" />
<input type='submit' value='Upload!' />
</form>
</body>
</html>

View File

@ -0,0 +1,41 @@
const express = require('express');
const fileUpload = require('../lib/index');
const app = express();
const PORT = 8000;
app.use('/form', express.static(__dirname + '/index.html'));
// default options
app.use(fileUpload());
app.get('/ping', function(req, res) {
res.send('pong');
});
app.post('/upload', function(req, res) {
let sampleFile;
let uploadPath;
if (Object.keys(req.files).length == 0) {
res.status(400).send('No files were uploaded.');
return;
}
console.log('req.files >>>', req.files); // eslint-disable-line
sampleFile = req.files.sampleFile;
uploadPath = __dirname + '/uploads/' + sampleFile.name;
sampleFile.mv(uploadPath, function(err) {
if (err) {
return res.status(500).send(err);
}
res.send('File uploaded to ' + uploadPath);
});
});
app.listen(PORT, function() {
console.log('Express server listening on port ', PORT); // eslint-disable-line
});

View File

@ -0,0 +1 @@
files are placed here when uploaded using the upload.test.js express server

View File

@ -0,0 +1,100 @@
'use strict';
const fs = require('fs');
const path = require('path');
const streamifier = require('streamifier');
const md5 = require('md5');
module.exports = function(options, fileUploadOptions = null) {
const output = {
name: options.name,
data: options.buffer,
encoding: options.encoding,
tempFilePath: options.tempFilePath,
truncated: options.truncated,
mimetype: options.mimetype,
md5: () => md5(options.buffer),
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();
});
}
}
};
if (options.size) {
output.size = options.size;
}
return output;
};

View File

@ -0,0 +1,37 @@
'use strict';
const fileFactory = require('./fileFactory');
const processMultipart = require('./processMultipart');
const isEligibleRequest = require('./isEligibleRequest');
const processNested = require('./processNested');
const fileUploadOptionsDefaults = {
safeFileNames: false,
preserveExtension: false,
abortOnLimit: false,
createParentPath: false,
parseNested: false,
useTempFiles: false,
tempFileDir: '/tmp'
};
/**
* Expose the file upload middleware
*/
module.exports = function(fileUploadOptions) {
fileUploadOptions = Object.assign({}, fileUploadOptionsDefaults, fileUploadOptions || {});
return function(req, res, next) {
if (!isEligibleRequest(req)) {
return next();
}
processMultipart(fileUploadOptions, req, res, next);
};
};
/**
* Quietly expose fileFactory and processNested; useful for testing
*/
module.exports.fileFactory = fileFactory;
module.exports.processNested = processNested;

View File

@ -0,0 +1,44 @@
const ACCEPTABLE_CONTENT_TYPE = /^(?:multipart\/.+)$/i;
const UNACCEPTABLE_METHODS = [
'GET',
'HEAD'
];
/**
* Ensures that the request in question is eligible for file uploads
* @param {Object} req Express req object
*/
module.exports = function(req) {
return hasBody(req) && hasAcceptableMethod(req) && hasAcceptableContentType(req);
};
/**
* Ensures the request is not using a non-compliant multipart method
* such as GET or HEAD
* @param {Object} req Express req object
* @return {Boolean}
*/
function hasAcceptableMethod(req) {
return (UNACCEPTABLE_METHODS.indexOf(req.method) < 0);
}
/**
* Ensures that only multipart requests are processed by express-fileupload
* @param {Object} req Express req object
* @return {Boolean}
*/
function hasAcceptableContentType(req) {
let str = (req.headers['content-type'] || '').split(';')[0];
return ACCEPTABLE_CONTENT_TYPE.test(str);
}
/**
* Ensures the request contains a content body
* @param {Object} req Express req object
* @return {Boolean}
*/
function hasBody(req) {
return ('transfer-encoding' in req.headers) ||
('content-length' in req.headers && req.headers['content-length'] !== '0');
}

View File

@ -0,0 +1,176 @@
const Busboy = require('busboy');
const fileFactory = require('./fileFactory');
const {
getTempFilePath,
complete,
cleanupStream,
tempFileHandler
} = require('./tempFileHandler');
const processNested = require('./processNested');
/**
* Processes multipart request
* Builds a req.body object for fields
* Builds a req.files object for files
* @param {Object} options expressFileupload and Busboy options
* @param {Object} req Express request object
* @param {Object} res Express response object
* @param {Function} next Express next method
* @return {void}
*/
module.exports = function processMultipart(options, req, res, next) {
let busboyOptions = {};
let busboy;
req.files = null;
// Build busboy config
for (let k in options) {
if (Object.prototype.hasOwnProperty.call(options, k)) {
busboyOptions[k] = options[k];
}
}
// Attach request headers to busboy config
busboyOptions.headers = req.headers;
// Init busboy instance
busboy = new Busboy(busboyOptions);
// Build multipart req.body fields
busboy.on('field', function(fieldname, val) {
req.body = req.body || {};
let prev = req.body[fieldname];
if (!prev) {
return (req.body[fieldname] = val);
}
if (Array.isArray(prev)) {
return prev.push(val);
}
req.body[fieldname] = [prev, val];
});
// Build req.files fields
busboy.on('file', function(fieldname, file, filename, encoding, mime) {
const buffers = [];
let safeFileNameRegex = /[^\w-]/g;
const memHandler = function(data) {
buffers.push(data);
if (options.debug) {
return console.log('Uploading %s -> %s', fieldname, filename); // eslint-disable-line
}
};
const dataHandler = options.useTempFiles
? tempFileHandler(options, fieldname, filename)
: memHandler;
file.on('limit', () => {
if (options.abortOnLimit) {
res.writeHead(413, { Connection: 'close' });
res.end('File size limit has been reached');
}
});
file.on('data', dataHandler);
file.on('end', function() {
if (!req.files) {
req.files = {};
}
if (options.useTempFiles) {
complete(filename);
}
const buffer = Buffer.concat(buffers);
// see: https://github.com/richardgirges/express-fileupload/issues/14
// firefox uploads empty file in case of cache miss when f5ing page.
// resulting in unexpected behavior. if there is no file data, the file is invalid.
if (!buffer.length && !options.useTempFiles) {
return;
}
if (options.safeFileNames) {
let maxExtensionLength = 3;
let extension = '';
if (typeof options.safeFileNames === 'object') {
safeFileNameRegex = options.safeFileNames;
}
maxExtensionLength = parseInt(options.preserveExtension);
if (options.preserveExtension || maxExtensionLength === 0) {
if (isNaN(maxExtensionLength)) {
maxExtensionLength = 3;
} else {
maxExtensionLength = Math.abs(maxExtensionLength);
}
let filenameParts = filename.split('.');
let filenamePartsLen = filenameParts.length;
if (filenamePartsLen > 1) {
extension = filenameParts.pop();
if (
extension.length > maxExtensionLength &&
maxExtensionLength > 0
) {
filenameParts[filenameParts.length - 1] +=
'.' +
extension.substr(0, extension.length - maxExtensionLength);
extension = extension.substr(-maxExtensionLength);
}
extension = maxExtensionLength
? '.' + extension.replace(safeFileNameRegex, '')
: '';
filename = filenameParts.join('.');
}
}
filename = filename.replace(safeFileNameRegex, '').concat(extension);
}
const newFile = fileFactory(
{
name: filename,
buffer,
tempFilePath: getTempFilePath(),
encoding,
truncated: file.truncated,
mimetype: mime
},
options
);
// Non-array fields
if (!req.files.hasOwnProperty(fieldname)) {
req.files[fieldname] = newFile;
} else {
// Array fields
if (req.files[fieldname] instanceof Array) {
req.files[fieldname].push(newFile);
} else {
req.files[fieldname] = [req.files[fieldname], newFile];
}
}
});
file.on('error', cleanupStream, next);
});
busboy.on('finish', () => {
if (options.parseNested) {
req.body = processNested(req.body);
req.files = processNested(req.files);
}
next();
});
busboy.on('error', next);
req.pipe(busboy);
};

View File

@ -0,0 +1,28 @@
module.exports = function(data){
if (!data || data.length < 1) return {};
let d = {},
keys = Object.keys(data);
for (let i = 0; i < keys.length; i++) {
let key = keys[i],
value = data[key],
current = d,
keyParts = key
.replace(new RegExp(/\[/g), '.')
.replace(new RegExp(/\]/g), '')
.split('.');
for (let index = 0; index < keyParts.length; index++){
let k = keyParts[index];
if (index >= keyParts.length - 1){
current[k] = value;
} else {
if (!current[k]) current[k] = !isNaN(keyParts[index + 1]) ? [] : {};
current = current[k];
}
}
}
return d;
};

View File

@ -0,0 +1,42 @@
const fs = require('fs');
let writeStream;
let tempFilePath;
module.exports.getTempFilePath = function() {
return tempFilePath;
};
module.exports.cleanupStream = function() {
writeStream.end();
fs.unlink(tempFilePath, function(err) {
if (err) throw err;
});
};
module.exports.complete = function(){
writeStream.end();
};
module.exports.tempFileHandler = function(options, fieldname, filename) {
const dir = __dirname + (options.tempFileDir || '/tmp/');
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
tempFilePath = dir + 'tmp' + Date.now();
writeStream = fs.createWriteStream(tempFilePath);
let fileSize = 0; // eslint-disable-line
return function(data) {
writeStream.write(data);
fileSize += data.length;
if (options.debug) {
return console.log( // eslint-disable-line
`Uploaded ${data.length} bytes for `,
fieldname,
filename
);
}
};
};

View File

@ -0,0 +1,78 @@
{
"_from": "express-fileupload",
"_id": "express-fileupload@1.1.1-alpha.1",
"_inBundle": false,
"_integrity": "sha512-zyZXaguQWdBT6kZL5HIuV//PCpmGKbYlDvu4FEpayeS3ONWwMaELDQPUgyyrEEbCyUhFmqrdHCkCUGL5LMVKEQ==",
"_location": "/express-fileupload",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "express-fileupload",
"name": "express-fileupload",
"escapedName": "express-fileupload",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.1.1-alpha.1.tgz",
"_shasum": "cfb452c971e0cc949cc3ccdb1ef578e8afb64716",
"_spec": "express-fileupload",
"_where": "D:\\5CHITM\\Diplomarbeit\\repos\\SmartShopper\\express-server",
"author": {
"name": "Richard Girges",
"email": "richardgirges@gmail.com"
},
"bugs": {
"url": "https://github.com/richardgirges/express-fileupload/issues"
},
"bundleDependencies": false,
"dependencies": {
"busboy": "^0.2.14",
"md5": "^2.2.1",
"streamifier": "^0.1.1"
},
"deprecated": false,
"description": "Simple express file upload middleware that wraps around Busboy",
"devDependencies": {
"body-parser": "^1.18.3",
"coveralls": "^3.0.2",
"eslint": "^5.9.0",
"express": "^4.16.3",
"istanbul": "^0.4.5",
"mocha": "^5.2.0",
"rimraf": "^2.6.2",
"supertest": "^3.3.0"
},
"engines": {
"node": ">=4.0.0"
},
"homepage": "https://github.com/richardgirges/express-fileupload#readme",
"keywords": [
"express",
"file-upload",
"upload",
"forms",
"multipart",
"files",
"busboy",
"middleware"
],
"license": "MIT",
"main": "./lib/index",
"name": "express-fileupload",
"repository": {
"type": "git",
"url": "git+https://github.com/richardgirges/express-fileupload.git"
},
"scripts": {
"coveralls": "cat ./coverage/lcov.info | coveralls",
"lint": "eslint ./",
"test": "istanbul cover _mocha -- -R spec"
},
"version": "1.1.1-alpha.1"
}

View File

@ -0,0 +1,78 @@
'use strict';
const assert = require('assert');
const fs = require('fs');
const md5 = require('md5');
const path = require('path');
const fileFactory = require('../lib').fileFactory;
const server = require('./server');
const mockBuffer = fs.readFileSync(path.join(server.fileDir, 'basketball.png'));
describe('Test of the fileFactory factory', function() {
beforeEach(function() {
server.clearUploadsDir();
});
it('return a file object', function() {
assert.ok(fileFactory({
name: 'basketball.png',
buffer: mockBuffer
}));
});
describe('File object behavior', function() {
const file = fileFactory({
name: 'basketball.png',
buffer: mockBuffer
});
it('move the file to the specified folder', function(done) {
file.mv(path.join(server.uploadDir, 'basketball.png'), function(err) {
assert.ifError(err);
done();
});
});
it('reject the mv if the destination does not exists', function(done) {
file.mv(path.join(server.uploadDir, 'unknown', 'basketball.png'), function(err) {
assert.ok(err);
done();
});
});
});
describe('Properties', function() {
it('contains the name property', function() {
assert.equal(fileFactory({
name: 'basketball.png',
buffer: mockBuffer
}).name, 'basketball.png');
});
it('contains the data property', function() {
assert.ok(fileFactory({
name: 'basketball.png',
buffer: mockBuffer
}).data);
});
it('contains the encoding property', function() {
assert.equal(fileFactory({
name: 'basketball.png',
buffer: mockBuffer,
encoding: 'utf-8'
}).encoding, 'utf-8');
});
it('contains the mimetype property', function() {
assert.equal(fileFactory({
name: 'basketball.png',
buffer: mockBuffer,
mimetype: 'image/png'
}).mimetype, 'image/png');
});
it('contains the md5 property', function() {
const mockMd5 = md5(mockBuffer);
assert.equal(fileFactory({
name: 'basketball.png',
buffer: mockBuffer
}).md5(), mockMd5);
});
});
});

View File

@ -0,0 +1,66 @@
'use strict';
const path = require('path');
const request = require('supertest');
const assert = require('assert');
const server = require('./server');
const clearUploadsDir = server.clearUploadsDir;
const fileDir = server.fileDir;
describe('Test Single File Upload With File Size Limit', function() {
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/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);
});
});
describe('pass truncated file to the next handler', function() {
before(function() {
app = server.setup({
limits: {fileSize: 200 * 1024} // set 200kb upload limit
});
});
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(400)
.end(function(err, res) {
assert.ok(res.error.text === 'File too big');
done();
});
});
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 KiB

View File

@ -0,0 +1,85 @@
'use strict';
const request = require('supertest');
const server = require('./server');
const app = server.setup();
let mockUser = {
firstName: 'Joe',
lastName: 'Schmo',
email: 'joe@mailinator.com'
};
let mockCars = [
'rsx',
'tsx',
'civic',
'integra'
];
describe('Test Multipart Form Single Field Submissions', function() {
it('submit multipart user data with POST', function(done) {
request(app)
.post('/fields/user')
.field('firstName', mockUser.firstName)
.field('lastName', mockUser.lastName)
.field('email', mockUser.email)
.expect('Content-Type', /json/)
.expect(200, {
firstName: mockUser.firstName,
lastName: mockUser.lastName,
email: mockUser.email
}, done);
});
it('submit multipart user data with PUT', function(done) {
request(app)
.post('/fields/user')
.field('firstName', mockUser.firstName)
.field('lastName', mockUser.lastName)
.field('email', mockUser.email)
.expect('Content-Type', /json/)
.expect(200, {
firstName: mockUser.firstName,
lastName: mockUser.lastName,
email: mockUser.email
}, done);
});
it('fail when user data submitted without multipart', function(done) {
request(app)
.post('/fields/user')
.send(mockUser)
.expect(400)
.end(done);
});
it('fail when user data not submitted', function(done) {
request(app)
.post('/fields/user')
.expect(400)
.end(done);
});
});
describe('Test Multipart Form Array Field Submissions', function() {
it('submit array of data with POST', function(done) {
let req = request(app).post('/fields/array');
for (let i = 0; i < mockCars.length; i++) {
req.field('testField', mockCars[i]);
}
req
.expect(200)
.end(function(err, res) {
if (err) {
return done(err);
}
let responseMatchesRequest = res.body.join(',') === mockCars.join(',');
done(responseMatchesRequest ? null : 'Data was returned as expected.');
});
});
});

View File

@ -0,0 +1,294 @@
'use strict';
const fs = require('fs');
const path = require('path');
const request = require('supertest');
const server = require('./server');
const app = server.setup();
const clearUploadsDir = server.clearUploadsDir;
const fileDir = server.fileDir;
const uploadDir = server.uploadDir;
const mockFiles = [
'car.png',
'tree.png',
'basketball.png'
];
let mockUser = {
firstName: 'Joe',
lastName: 'Schmo',
email: 'joe@mailinator.com'
};
describe('Test Directory Cleaning Method', function() {
it('emptied "uploads" directory', function(done) {
clearUploadsDir();
let filesFound = fs.readdirSync(uploadDir).length;
done(filesFound ? `Directory not empty. Found ${filesFound} files.` : null);
});
});
describe('Test Single File Upload', function() {
for (let i = 0; i < mockFiles.length; i++) {
let fileName = mockFiles[i];
it(`upload ${fileName} with POST`, function(done) {
let filePath = path.join(fileDir, fileName);
let uploadedFilePath = path.join(uploadDir, fileName);
clearUploadsDir();
request(app)
.post('/upload/single')
.attach('testFile', filePath)
.expect(200)
.end(function(err) {
if (err) {
return done(err);
}
fs.stat(uploadedFilePath, done);
});
});
it(`upload ${fileName} with PUT`, function(done) {
let filePath = path.join(fileDir, fileName);
let uploadedFilePath = path.join(uploadDir, fileName);
clearUploadsDir();
request(app)
.post('/upload/single')
.attach('testFile', filePath)
.expect(200)
.end(function(err) {
if (err) {
return done(err);
}
fs.stat(uploadedFilePath, done);
});
});
}
it('fail when no files were attached', function(done) {
request(app)
.post('/upload/single')
.expect(400)
.end(done);
});
it('fail when using GET', function(done) {
let filePath = path.join(fileDir, mockFiles[0]);
request(app)
.get('/upload/single')
.attach('testFile', filePath)
.expect(400)
.end(done);
});
it('fail when using HEAD', function(done) {
let filePath = path.join(fileDir, mockFiles[0]);
request(app)
.head('/upload/single')
.attach('testFile', filePath)
.expect(400)
.end(done);
});
});
describe('Test Single File Upload w/ .mv() Promise', function() {
for (let i = 0; i < mockFiles.length; i++) {
let fileName = mockFiles[i];
it(`upload ${fileName} with POST w/ .mv() Promise`, function(done) {
let filePath = path.join(fileDir, fileName);
let uploadedFilePath = path.join(uploadDir, fileName);
clearUploadsDir();
request(app)
.post('/upload/single/promise')
.attach('testFile', filePath)
.expect(200)
.end(function(err) {
if (err) {
return done(err);
}
fs.stat(uploadedFilePath, done);
});
});
it(`upload ${fileName} with PUT w/ .mv() Promise`, function(done) {
let filePath = path.join(fileDir, fileName);
let uploadedFilePath = path.join(uploadDir, fileName);
clearUploadsDir();
request(app)
.post('/upload/single/promise')
.attach('testFile', filePath)
.expect(200)
.end(function(err) {
if (err) {
return done(err);
}
fs.stat(uploadedFilePath, done);
});
});
}
it('fail when no files were attached', function(done) {
request(app)
.post('/upload/single')
.expect(400)
.end(done);
});
it('fail when using GET', function(done) {
let filePath = path.join(fileDir, mockFiles[0]);
request(app)
.get('/upload/single')
.attach('testFile', filePath)
.expect(400)
.end(done);
});
it('fail when using HEAD', function(done) {
let filePath = path.join(fileDir, mockFiles[0]);
request(app)
.head('/upload/single')
.attach('testFile', filePath)
.expect(400)
.end(done);
});
});
describe('Test Multi-File Upload', function() {
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]);
clearUploadsDir();
request(app)
.post('/upload/multiple')
.attach('testFile1', upload1)
.attach('testFile2', upload2)
.attach('testFile3', upload3)
.expect(200)
.end(function(err) {
if (err) {
return done(err);
}
fs.stat(upload1, function(err) {
if (err) {
return done(err);
}
fs.stat(upload2, function(err) {
if (err) {
return done(err);
}
fs.stat(upload3, done);
});
});
});
});
});
describe('Test File Array Upload', function() {
it('upload array of files with POST', function(done) {
let req = request(app).post('/upload/array');
clearUploadsDir();
for (let i = 0; i < mockFiles.length; i++) {
req.attach('testFiles', path.join(fileDir, mockFiles[i]));
}
req
.expect(200)
.end(function(err) {
if (err) {
return done(err);
}
for (let i = 0; i < mockFiles.length; i++) {
fs.statSync(path.join(uploadDir, mockFiles[i]));
}
done();
});
});
});
describe('Test Upload With Fields', function() {
for (let i = 0; i < mockFiles.length; i++) {
let fileName = mockFiles[i];
it(`upload ${fileName} and submit fields at the same time with POST`, function(done) {
let filePath = path.join(fileDir, fileName);
let uploadedFilePath = path.join(uploadDir, fileName);
clearUploadsDir();
request(app)
.post('/upload/single/withfields')
.attach('testFile', filePath)
.field('firstName', mockUser.firstName)
.field('lastName', mockUser.lastName)
.field('email', mockUser.email)
.expect(200, {
firstName: mockUser.firstName,
lastName: mockUser.lastName,
email: mockUser.email
},
function(err) {
if (err) {
return done(err);
}
fs.stat(uploadedFilePath, done);
});
});
it(`upload ${fileName} and submit fields at the same time with PUT`, function(done) {
let filePath = path.join(fileDir, fileName);
let uploadedFilePath = path.join(uploadDir, fileName);
clearUploadsDir();
request(app)
.put('/upload/single/withfields')
.attach('testFile', filePath)
.field('firstName', mockUser.firstName)
.field('lastName', mockUser.lastName)
.field('email', mockUser.email)
.expect(200, {
firstName: mockUser.firstName,
lastName: mockUser.lastName,
email: mockUser.email
},
function(err) {
if (err) {
return done(err);
}
fs.stat(uploadedFilePath, done);
});
});
}
});

View File

@ -0,0 +1,219 @@
const fs = require('fs');
const path = require('path');
const request = require('supertest');
const server = require('./server');
const clearUploadsDir = server.clearUploadsDir;
const fileDir = server.fileDir;
const uploadDir = server.uploadDir;
describe('File Upload Options Tests', function() {
afterEach(function(done) {
clearUploadsDir();
done();
});
/**
* Upload the file for testing and verify the expected filename.
* @param {object} options The expressFileUpload options.
* @param {string} actualFileNameToUpload The name of the file to upload.
* @param {string} expectedFileNameOnFileSystem The name of the file after upload.
* @param {function} done The mocha continuation function.
*/
function executeFileUploadTestWalk(options,
actualFileNameToUpload,
expectedFileNameOnFileSystem,
done) {
request(server.setup(options))
.post('/upload/single')
.attach('testFile', path.join(fileDir, actualFileNameToUpload))
.expect(200)
.end(function(err) {
if (err) {
return done(err);
}
const uploadedFilePath = path.join(uploadDir, expectedFileNameOnFileSystem);
fs.stat(uploadedFilePath, done);
});
}
describe('Testing [safeFileNames] option to ensure:', function() {
it('Does nothing to your filename when disabled.',
function(done) {
const fileUploadOptions = {safeFileNames: false};
const actualFileName = 'my$Invalid#fileName.png123';
const expectedFileName = 'my$Invalid#fileName.png123';
executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done);
});
it('Is disabled by default.',
function(done) {
const fileUploadOptions = null;
const actualFileName = 'my$Invalid#fileName.png123';
const expectedFileName = 'my$Invalid#fileName.png123';
executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done);
});
it('Strips away all non-alphanumeric characters (excluding hyphens/underscores) when enabled.',
function(done) {
const fileUploadOptions = {safeFileNames: true};
const actualFileName = 'my$Invalid#fileName.png123';
const expectedFileName = 'myInvalidfileNamepng123';
executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done);
});
it('Accepts a regex for stripping (decidedly) "invalid" characters from filename.',
function(done) {
const fileUploadOptions = {safeFileNames: /[$#]/g};
const actualFileName = 'my$Invalid#fileName.png123';
const expectedFileName = 'myInvalidfileName.png123';
executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done);
});
});
describe('Testing [preserveExtension] option to ensure:', function() {
it('Does not preserve the extension of your filename when disabled.',
function(done) {
const fileUploadOptions = {safeFileNames: true, preserveExtension: false};
const actualFileName = 'my$Invalid#fileName.png123';
const expectedFileName = 'myInvalidfileNamepng123';
executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done);
});
it('Is disabled by default.',
function(done) {
const fileUploadOptions = {safeFileNames: true};
const actualFileName = 'my$Invalid#fileName.png123';
const expectedFileName = 'myInvalidfileNamepng123';
executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done);
});
it('Shortens your extension to the default(3) when enabled, if the extension found is larger.',
function(done) {
const fileUploadOptions = {safeFileNames: true, preserveExtension: true};
const actualFileName = 'my$Invalid#fileName.png123';
const expectedFileName = 'myInvalidfileNamepng.123';
executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done);
});
it('Leaves your extension alone when enabled, if the extension found is <= default(3) length',
function(done) {
const fileUploadOptions = {safeFileNames: true, preserveExtension: true};
const actualFileName = 'car.png';
const expectedFileName = 'car.png';
executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done);
});
it('Can be configured for an extension length > default(3).',
function(done) {
const fileUploadOptions = {safeFileNames: true, preserveExtension: 7};
const actualFileName = 'my$Invalid#fileName.png123';
const expectedFileName = 'myInvalidfileName.png123';
executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done);
});
it('Can be configured for an extension length < default(3).',
function(done) {
const fileUploadOptions = {safeFileNames: true, preserveExtension: 2};
const actualFileName = 'my$Invalid#fileName.png123';
const expectedFileName = 'myInvalidfileNamepng1.23';
executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done);
});
it('Will use the absolute value of your extension length when negative.',
function(done) {
const fileUploadOptions = {safeFileNames: true, preserveExtension: -5};
const actualFileName = 'my$Invalid#fileName.png123';
const expectedFileName = 'myInvalidfileNamep.ng123';
executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done);
});
it('Will leave no extension when the extension length == 0.',
function(done) {
const fileUploadOptions = {safeFileNames: true, preserveExtension: 0};
const actualFileName = 'car.png';
const expectedFileName = 'car';
executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done);
});
it('Will accept numbers as strings, if they can be resolved with parseInt.',
function(done) {
const fileUploadOptions = {safeFileNames: true, preserveExtension: '3'};
const actualFileName = 'my$Invalid#fileName.png123';
const expectedFileName = 'myInvalidfileNamepng.123';
executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done);
});
it('Will be evaluated for truthy-ness if it cannot be parsed as an int.',
function(done) {
const fileUploadOptions = {safeFileNames: true, preserveExtension: 'not-a-#-but-truthy'};
const actualFileName = 'my$Invalid#fileName.png123';
const expectedFileName = 'myInvalidfileNamepng.123';
executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done);
});
it('Will ignore any decimal amount when evaluating for extension length.',
function(done) {
const fileUploadOptions = {safeFileNames: true, preserveExtension: 4.98};
const actualFileName = 'my$Invalid#fileName.png123';
const expectedFileName = 'myInvalidfileNamepn.g123';
executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done);
});
it('Only considers the last dotted part as the extension.',
function(done) {
const fileUploadOptions = {safeFileNames: true, preserveExtension: true};
const actualFileName = 'basket.ball.bp';
const expectedFileName = 'basketball.bp';
executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done);
});
});
describe('Testing [parseNested] option to ensure:', function() {
it('When [parseNested] is enabled result are nested', function(done){
const app = server.setup({parseNested: true});
request(app)
.post('/fields/nested')
.field('name', 'John')
.field('hobbies[0]', 'Cinema')
.field('hobbies[1]', 'Bike')
.expect('Content-Type', /json/)
.expect(200, {
name: 'John',
hobbies: ['Cinema', 'Bike']
}, done);
});
it('When [parseNested] is disabled are flattened', function(done){
const app = server.setup({parseNested: false});
request(app)
.post('/fields/flattened')
.field('name', 'John')
.field('hobbies[0]', 'Cinema')
.field('hobbies[1]', 'Bike')
.expect('Content-Type', /json/)
.expect(200, {
name: 'John',
'hobbies[0]': 'Cinema',
'hobbies[1]': 'Bike'
}, done);
});
});
});

View File

@ -0,0 +1,48 @@
'use strict';
const assert = require('assert');
const processNested = require('../lib').processNested;
describe('Test Convert Flatten object to Nested object', function() {
it('With no nested data', function(){
const data = {
'firstname': 'John',
'lastname': 'Doe',
'age': 22
},
excerpt= { firstname: 'John', lastname: 'Doe', age: 22 },
processed = processNested(data);
assert.deepEqual(processed, excerpt);
});
it('With nested data', function(){
const data = {
'firstname': 'John',
'lastname': 'Doe',
'age': 22,
'hobbies[0]': 'Cinema',
'hobbies[1]': 'Bike',
'address[line]': '78 Lynch Street',
'address[city]': 'Milwaukee',
'friends[0][name]': 'Jane',
'friends[0][lastname]': 'Doe',
'friends[1][name]': 'Joe',
'friends[1][lastname]': 'Doe'
},
excerpt = {
firstname: 'John',
lastname: 'Doe',
age: 22,
hobbies: [ 'Cinema', 'Bike' ],
address: { line: '78 Lynch Street', city: 'Milwaukee' },
friends: [
{ name: 'Jane', lastname: 'Doe' },
{ name: 'Joe', lastname: 'Doe' }
]
},
processed = processNested(data);
assert.deepEqual(processed, excerpt);
});
});

View File

@ -0,0 +1,284 @@
'use strict';
const path = require('path');
const fileDir = path.join(__dirname, 'files');
const uploadDir = path.join(__dirname, 'uploads');
const fs = require('fs');
const rimraf = require('rimraf');
const clearUploadsDir = function() {
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir);
} else {
rimraf.sync(uploadDir);
fs.mkdirSync(uploadDir);
}
};
const setup = function(fileUploadOptions) {
const express = require('express');
const expressFileupload = require('../lib/index');
const app = express();
fileUploadOptions = fileUploadOptions || {};
app.use(expressFileupload(fileUploadOptions));
app.all('/upload/single', function(req, res) {
if (!req.files) {
return res.status(400).send('No files were uploaded.');
}
let testFile = req.files.testFile;
let uploadPath = path.join(uploadDir, testFile.name);
testFile.mv(uploadPath, function(err) {
if (err) {
console.log('ERR', err); // eslint-disable-line
return res.status(500).send(err);
}
res.send('File uploaded to ' + uploadPath);
});
});
app.all('/upload/single/promise', function(req, res) {
if (!req.files) {
return res.status(400).send('No files were uploaded.');
}
let testFile = req.files.testFile;
let uploadPath = path.join(uploadDir, testFile.name);
testFile
.mv(uploadPath)
.then(() => {
res.send('File uploaded to ' + uploadPath);
})
.catch(err => {
res.status(500).send(err);
});
});
app.all('/upload/single/withfields', function(req, res) {
if (!req.files) {
return res.status(400).send('No files were uploaded.');
}
if (!req.body) {
return res.status(400).send('No request body found');
}
if (!req.body.firstName || !req.body.firstName.trim()) {
return res.status(400).send('Invalid first name');
}
if (!req.body.lastName || !req.body.lastName.trim()) {
return res.status(400).send('Invalid last name');
}
if (!req.body.email || !req.body.email.trim()) {
return res.status(400).send('Invalid email');
}
let testFile = req.files.testFile;
let uploadPath = path.join(uploadDir, testFile.name);
testFile.mv(uploadPath, function(err) {
if (err) {
return res.status(500).send(err);
}
res.json({
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email
});
});
});
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.');
}
let testFile1 = req.files.testFile1;
let testFile2 = req.files.testFile2;
let testFile3 = req.files.testFile3;
let uploadPath1 = path.join(uploadDir, testFile1.name);
let uploadPath2 = path.join(uploadDir, testFile2.name);
let uploadPath3 = path.join(uploadDir, testFile3.name);
if (!testFile1) {
return res.status(400).send('testFile1 was not uploaded');
}
if (!testFile2) {
return res.status(400).send('testFile2 was not uploaded');
}
if (!testFile3) {
return res.status(400).send('testFile3 was not uploaded');
}
testFile1.mv(uploadPath1, function(err) {
if (err) {
return res.status(500).send(err);
}
testFile2.mv(uploadPath2, function(err) {
if (err) {
return res.status(500).send(err);
}
testFile3.mv(uploadPath3, function(err) {
if (err) {
return res.status(500).send(err);
}
res.send('Files uploaded to ' + uploadDir);
});
});
});
});
app.all('/upload/array', function(req, res) {
if (!req.files) {
return res.status(400).send('No files were uploaded.');
}
let testFiles = req.files.testFiles;
if (!testFiles) {
return res.status(400).send('No files were uploaded');
}
if (!Array.isArray(testFiles)) {
return res.status(400).send('Files were not uploaded as an array');
}
if (!testFiles.length) {
return res.status(400).send('Files array is empty');
}
let filesUploaded = 0;
for (let i = 0; i < testFiles.length; i++) {
let uploadPath = path.join(uploadDir, testFiles[i].name);
testFiles[i].mv(uploadPath, function(err) {
if (err) {
return res.status(500).send(err);
}
if (++filesUploaded === testFiles.length) {
res.send('File uploaded to ' + uploadPath);
}
});
}
});
app.all('/fields/user', function(req, res) {
if (!req.body) {
return res.status(400).send('No request body found');
}
if (!req.body.firstName || !req.body.firstName.trim()) {
return res.status(400).send('Invalid first name');
}
if (!req.body.lastName || !req.body.lastName.trim()) {
return res.status(400).send('Invalid last name');
}
if (!req.body.email || !req.body.email.trim()) {
return res.status(400).send('Invalid email');
}
res.json({
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email
});
});
app.all('/fields/nested', function(req, res) {
if (!req.body) {
return res.status(400).send('No request body found');
}
if (!req.body.name || !req.body.name.trim()) {
return res.status(400).send('Invalid name');
}
if (!req.body.hobbies || !req.body.hobbies.length == 2) {
return res.status(400).send('Invalid hobbies');
}
res.json({
name: req.body.name,
hobbies: req.body.hobbies
});
});
app.all('/fields/flattened', function(req, res) {
if (!req.body) {
return res.status(400).send('No request body found');
}
if (!req.body.name || !req.body.name.trim()) {
return res.status(400).send('Invalid name');
}
if (!req.body['hobbies[0]'] || !req.body['hobbies[0]'].trim()) {
return res.status(400).send('Invalid hobbies[0]');
}
if (!req.body['hobbies[1]'] || !req.body['hobbies[1]'].trim()) {
return res.status(400).send('Invalid hobbies[1]');
}
res.json({
name: req.body.name,
'hobbies[0]': req.body['hobbies[0]'],
'hobbies[1]': req.body['hobbies[1]']
});
});
app.all('/fields/array', function(req, res) {
if (!req.body) {
return res.status(400).send('No request body found');
}
if (!req.body.testField) {
return res.status(400).send('Invalid field');
}
if (!Array.isArray(req.body.testField)) {
return res.status(400).send('Field is not an array');
}
res.json(req.body.testField);
});
return app;
};
module.exports = {
setup,
fileDir,
uploadDir,
clearUploadsDir
};

View File

@ -0,0 +1,126 @@
const fs = require('fs');
const path = require('path');
const request = require('supertest');
const server = require('./server');
const clearUploadsDir =
server.clearUploadsDir;
const fileDir =
server.fileDir;
const uploadDir =
server.uploadDir;
describe('File Upload Options Tests', function() {
afterEach(function(done) {
clearUploadsDir();
done();
});
/**
* Upload the file for testing and verify the expected filename.
* @param {object} options The expressFileUpload options.
* @param {string} actualFileNameToUpload The name of the file to upload.
* @param {string} expectedFileNameOnFileSystem The name of the file after upload.
* @param {function} done The mocha continuation function.
*/
function executeFileUploadTestWalk(
options,
actualFileNameToUpload,
expectedFileNameOnFileSystem,
done
) {
request(
server.setup(options)
)
.post('/upload/single')
.attach(
'testFile',
path.join(
fileDir,
actualFileNameToUpload
)
)
.expect(200)
.end(function(err) {
if (err) {
return done(err);
}
const uploadedFilePath = path.join(
uploadDir,
expectedFileNameOnFileSystem
);
fs.stat(
uploadedFilePath,
done
);
});
}
describe('Testing [safeFileNames with useTempFiles] option to ensure:', function() {
it('Does nothing to your filename when disabled.', function(done) {
const fileUploadOptions = {
safeFileNames: false,
useTempFiles: true,
tempFileDir: '/tmp/'
};
const actualFileName =
'my$Invalid#fileName.png123';
const expectedFileName =
'my$Invalid#fileName.png123';
executeFileUploadTestWalk(
fileUploadOptions,
actualFileName,
expectedFileName,
done
);
});
it('Is disabled by default.', function(done) {
const fileUploadOptions = {
useTempFiles: true,
tempFileDir: '/tmp/'
};
const actualFileName =
'my$Invalid#fileName.png123';
const expectedFileName =
'my$Invalid#fileName.png123';
executeFileUploadTestWalk(
fileUploadOptions,
actualFileName,
expectedFileName,
done
);
});
it(
'Strips away all non-alphanumeric characters (excluding hyphens/underscores) when enabled.',
function(done) {
const fileUploadOptions = {
safeFileNames: true,
useTempFiles: true,
tempFileDir: '/tmp/'
};
const actualFileName = 'my$Invalid#fileName.png123';
const expectedFileName = 'myInvalidfileNamepng123';
executeFileUploadTestWalk(
fileUploadOptions,
actualFileName,
expectedFileName,
done
);
});
it(
'Accepts a regex for stripping (decidedly) "invalid" characters from filename.',
function(done) {
const fileUploadOptions = {
safeFileNames: /[$#]/g,
useTempFiles: true,
tempFileDir: '/tmp/'
};
const actualFileName = 'my$Invalid#fileName.png123';
const expectedFileName = 'myInvalidfileName.png123';
executeFileUploadTestWalk(
fileUploadOptions,
actualFileName,
expectedFileName,
done
);
});
});
});