April 24, 2014 • 2 minute read
File Uploads with Express 4.0
One of the side projects I'm currently working on is a quick online ONIX for Books file validator utility. The tool is built using Node.js and Express, and I quickly ran into an issue with handling file uploads.
Searching Google didn't help all that much, particularly when it comes to Express 4.0, which no longer includes the Connect middleware that handles this kind of thing out of the box. After a little bit of digging, I came across the multer
middleware package.
To add multer to your Express project, use npm
to install it as follows (the --save
flag will add the dependecy to your package.json
file).
npm install multer --save
Next, you need to tell your Express app to use multer
. In your app.js
file, add a require
as follows:
var multer = require('multer');
Next, add an app.use
call somewhere above the module.exports = app
line in the same file:
app.use(multer({dest:'./uploads/'}));
This will tell multer
to store any uploaded files in the uploads
subdirectory in your project.
With multer
added to your app, you can now handle uploads in your views. My index route for the ONIX validator tool is as follows (stored in routes/index.js
):
router.get('/', function(req, res) {
res.render('index', { title: 'ONIX Validator' });
});
This renders a view named index.jade
in the views
directory. This view has a form with an file input element which allows the end user to select a file to upload to the server. For the upload to work, the <form>
element needs to have the enctype
attribute set to multipart/form-data
. The following is a snippet from my index.jade
file that illustrates this:
form(role="form", action="/", method="post", enctype="multipart/form-data")
div(class="form-group")
label(for="onixfile") Upload ONIX File
input(type="file", name="onixfile", id="onixfile")
This form will send a POST request to the /
route. In this route, you can now access the properties of the file that has been uploaded using req.files as follows:
router.post('/', function(req, res) {
console.dir(req.files);
});
This will output an object including various information about the file that was uploaded.
{
onixfile: {
fieldname: 'onixfile',
originalname: 'onix.xml',
name: '4f67055ab5ee865df8c1ca2b1bfd2083.xml',
encoding: '7bit',
mimetype: 'text/xml',
path: 'uploads/4f67055ab5ee865df8c1ca2b1bfd2083.xml',
extension: 'xml'
}
}
The most important property to take note of here is the path
property, which indicates where the uploaded file has been stored on the server.
WARNING When you have finished processing the uploaded file you should delete it from the filesystem. Otherwise an attacker could easily write a script that will bombard your server with file uploads in an attempt to fill its hard disk and bring the server down. If you need to store the file, consider storing it in a purpose-built file store such as Amazon S3, or adding security measures around the upload page.