Blog Portfolio

Image Upload with Node and Multer

Sat, Dec 3, 2016

This tutorial provides an end to end walkthrough of uploading images in Node with Multer.

To make things simple I am providing an app-template and complete code. Feel free to use the template or an app that you are working on.

App-Template

Complete Code

I am using Multer 1.2.0 and Node 6.4.0.

  1. Install Multer, Mime, and Cryto and save to dependencies.
  2.  `npm install -S multer`
    
     `npm install -S mime`
    
     `npm install -S crypto`
    
  3. Require depencies in route `index.js`
  4. var express = require('express'),
        router = express.Router(),
        mime = require('mime'),
        multer = require('multer');
    
  5. Create a form in `index.ejs`
  6. <form action="/upload" enctype="multipart/form-data" method="POST">
    Select an image to upload:
    <input name="image" type="file" />
    <input type="submit" value="Upload Image" />
    </form>
    
    The form `enctype` must be `multipart/form-data`, which is the encoding used for forms that upload files. The `enctype` specifies how the form-data is encoded when it is submitted to a server. When submitted, the form will send a POST request to our upload route. We will construct the route in a later step.
  7. Before we can write our upload route, we need to configure Multer's storage. Multer ships with two different storage engines, `DiskStorage` and `MemoryStorage`. I will be using `DiskStorage` which gives you full control over storing files to disk.
  8. Create a folder called `uploads` in `public`. In `index.js` underneath your require statements, write the following.
    var storage = multer.diskStorage({
      destination: function(req, file, cb) {
          cb(null, 'public/uploads/')
      },
      filename: function(req, file, cb) {
          crypto.pseudoRandomBytes(16, function(err, raw) {
              cb(null, raw.toString('hex') + Date.now() + '.' + mime.extension(file.mimetype));
          });
        }
    });
    
    var upload = multer({
      storage: storage
    });
    
    The two options for `DiskStorage`, `destination` and `filename`, are functions that determine where the file should be stored. As their name's suggest, destination determines the upload location and filename determines the filename. Multer does not provide a file extension for the upload, so the filename function must return a filename with an extension. Filename uses `Crypto` to generate a random name and uses `Mime` to determine the correct file extension. Generating a random filename prevents collisions if two files are uploaded with the same name. While not required, this is good practice. `upload` will be called to upload an image.
  9. Write upload route
  10. // POST Upload Image
    router.post('/upload', upload.single("image"), function(req, res) {
      res.send('<img src="/uploads/' + req.file.filename + '" />');
    });
    
    This route first uses Multer to upload the image and then sends a response to the client that includes the image, now hosted on the server. You should be all set, but if there are any issues please comment.

Sources

Multer

Multer Issue: Files are uploading as ‘file without its extension