Eric Bergman-Terrell's Blog

Node.js / Express Programming Tip: How to Upload Images
September 21, 2015

These days it is vital to spice up your web content with irrelevant photos. No one is going to read a bunch of boring words, without some fun graphics! And a technocrat like you isn't going to use FTP to upload custom images. You need a web UI to dynamically upload image files. On demand. When you demand it!

when sharks attack

With Node.js and Express, it's easy to add a photo upload facility. The first step is to create a basic upload form, and what could be more basic than this?

upload image form

This is the Upload form template: (I use the EJS template engine to render HTML)

<% layout('../layout') -%>
<h1><%= title %></h1>

<form accept-charset="UTF-8" action="/admin/upload/image" class="new_uploaded_image_file" enctype="multipart/form-data" id="new_uploaded_image_file" method="POST">
    <div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /></div>

    <input id="uploaded_image_file_photo" name="uploaded_image_file" type="file" />

    <br/><br/>
    <input name="commit" type="submit" value="Submit" />
</form>

Then use the following modules: formidable does form parsing. fs-extra provides filesystem access, and async orchestrates callbacks.

...
var formidable = require('formidable');
var fs = require('fs-extra');
var async = require('async');
...

There's nothing interesting about serving up the upload form:

function setupGet(app) {
    app.get('/admin/upload/image', function (req, res) {
        res.render('../views/upload/image', {title: 'Upload Image' });
    });
}

caution - rattlesnake country!

All the interesting things happen when the photo is being uploaded. After accessing the uploaded file using formidable, that file needs to be copied from the temp folder to the destination folder, and then removed from the source folder. If you happen to know that the temp folder will always be on the same volume as the target folder, you could do a "move" rather than a "copy and delete". That is definitely not the case for my website, when it's deployed on the server.

Upload photos in Node.js / Express

Note, you could call synchronous copy and remove methods to manipulate the image file, but that defeats one of the strengths of Node.js: the ability to run massive amounts of IO in the background, rather than blocking on synchronous code. Plus, the async module makes it super-easy to handle the asynchronous callbacks. There's no reason to use those blocking calls.

function setupPostUploadImage(app) {
    app.post('/admin/upload/image', function (req, res) {
        global.logger.info('post image');

        var form = new formidable.IncomingForm();
        form.parse(req, function (error, fields, files) {
            if (!error) {
                var file = files["uploaded_image_file"];

                async.series([
                        function (callback) {
                            global.logger.info('copying image ' + file.path + ' to ./public/uploaded_images/');

                            fs.copy(file.path, './public/uploaded_images/' + file.name, function (error) {
                                callback(error);
                            });
                        },
                        function (callback) {
                            fs.remove(file.path, function (error, removed) {
                                callback(error, removed);
                            });
                        }
                    ],
                    function (error, results) {
                        if (!error) {
                            res.redirect('/admin/upload/images');
                        }
                        else {
                            global.logger.error('Error uploading image: ' + error);
                            res.redirect('/error?message=12');
                        }
                    });
            }
        });
    });
}

On this website, only authorized users are allowed to upload photos. Only me, in fact. I recommend that you do the same thing, unless your website has a legitimate need to accept user-contributed files. You do not want to open your server's filesystem up to bad guys!

balloons
I'd really like a hamburger right now!

Keywords: Node.js, node, Express, graphics, file upload, upload, JPEG, JPG, Image, Upload, filesystem, fs-extra, synchronous and asynchronous calls, async, formidable

Reader Comments

Comment on this Blog Post

Recent Posts

TitleDate
Java Programming Tip: SWT Photo Frame ProgramOctober 31, 2016
Vault 3 (Desktop) Version 1.63 ReleasedSeptember 9, 2016
"Compliance with Court Orders Act of 2016"April 9, 2016
Disable "Visual Voicemail" on Android / T-MobileJanuary 17, 2016
IPv6 HumorDecember 10, 2015
Java Programming Tip: Specify the JVM time zoneDecember 7, 2015
Node.js / Express Programming Tip: Detect and Fix Memory LeaksOctober 27, 2015