a blog for those who code

Monday, 18 January 2016

File Upload in Node.js

In this post we will be discussing about file upload in Node.js. We will be using Multer which is a Node.js middleware for handling 'multipart/form-data'. It does not process any form which is not multipart. According to Multer, it adds a body object and a file or files object to the request object. The body object contains the values of the text fields of the form, the file or files object contains the files uploaded via the form.


File Upload in Node.js Code :

Server.js

var express = require('express');
var multer = require('multer');
var app = express();
var port = 5000;

app.set('port', port); 

/* Disk Storage engine of multer gives you full control on storing files to disk. The options are destination (for determining which folder the file should be saved) and filename (name of the file inside the folder) */

var storage = multer.diskStorage({
  destination: function (request, file, callback) {
    callback(null, '/example/uploads');
  },
  filename: function (request, file, callback) {
    console.log(file);
    callback(null, file.originalname)
  }
});

/*Multer accepts a single file with the name photo. This file will be stored in request.file*/

var upload = multer({storage: storage}).single('photo');

//Showing index.html file on our homepage
app.get('/', function(resuest, response) {
  response.sendFile('/example/index.html');
});

//Posting the file upload
app.post('/upload', function(request, response) {
  upload(request, response, function(err) {
  if(err) {
    console.log('Error Occured');
    return;
  }
  console.log(request.file);
  response.end('Your File Uploaded');
  console.log('Photo Uploaded');
  })
});

var server = app.listen(port, function () {
  console.log('Listening on port ' + server.address().port)
});

Index.html

<form enctype="multipart/form-data" action="/upload" method="post">
  <input type="file" name="photo" />
  <input type="submit" value="Upload Image" name="submit" />
</form>

If you run the above code and upload an image, your image will be uploaded in Uploads folder. You will get an output as shown below.


In our next post we will be discussing about Multiple file upload in Node.js. Please Like and Share the CodingDefined.com Blog, if you find it interesting and helpful.

7 comments:

  1. i tried using this example , shows this error :

    [Function: multerMiddleware]
    { fieldname: 'proPic',
    originalname: 'am92Dvo_700b.jpg',
    encoding: '7bit',
    mimetype: 'image/jpeg' }
    path.js:8
    throw new TypeError('Path must be a string. Received ' +
    ^

    TypeError: Path must be a string. Received undefined
    at assertPath (path.js:8:11)
    at Object.win32.join (path.js:221:5)
    at C:\Node Works\Fonebook\node_modules\multer\storage\disk.js:37:28
    at DiskStorage.multer.diskStorage.filename [as getFilename] (C:\Node Works\Fonebook\app.js:48:9)
    at C:\Node Works\Fonebook\node_modules\multer\storage\disk.js:34:10
    at DiskStorage.multer.diskStorage.destination [as getDestination] (C:\Node Works\Fonebook\app.js:44:9)
    at DiskStorage._handleFile (C:\Node Works\Fonebook\node_modules\multer\storage\disk.js:31:8)
    at C:\Node Works\Fonebook\node_modules\multer\lib\make-middleware.js:142:17
    at allowAll (C:\Node Works\Fonebook\node_modules\multer\index.js:8:3)
    at wrappedFileFilter (C:\Node Works\Fonebook\node_modules\multer\index.js:43:7)
    at Busboy. (C:\Node Works\Fonebook\node_modules\multer\lib\make-middleware.js:112:7)
    at emitMany (events.js:108:13)
    at Busboy.emit (events.js:182:7)
    at Busboy.emit (C:\Node Works\Fonebook\node_modules\busboy\lib\main.js:31:35)
    at PartStream. (C:\Node Works\Fonebook\node_modules\busboy\lib\types\multipart.js:208:13)
    at emitOne (events.js:77:13)


    please help

    ReplyDelete
    Replies
    1. You need to add path as string i.e. in quotes : callback(null, '/example/uploads');

      Delete
    2. Thank you! though i figured it out :p

      Delete
  2. Hi Hemant,

    I tried you example and seems to work fine.
    The only thing is couldn't figure out how to get form field values in diskstorage filename
    I need to set user given filename(in turn to store in db)
    Here is my code,

    var storage = multer.diskStorage({
    destination: function (request, file, callback) {
    callback( null, folderPath );
    },

    filename: function (request, file, callback) {
    altFileName = request.body.attAltFileName;
    // I Need to get request.body.attAltFileName here so that I can set that value as filename
    callback( null, file.originalname );
    }
    });

    var upload = multer({ storage : storage}).single('attFileUpload');

    upload( request, response, function(err) {
    var fName = request.body.attAltFileName;
    fileSingle = JSON.stringify(request.file);

    if( err ) {
    return responseCallback( err );
    }
    responseCallback( null, {altFileName: altFileName, fName: fName} );
    });

    I could get proper field value from upload() but not from diskStorage filename.
    Can you direct me what could be going wrong ??

    Here is my form snippet,

    form method="post" id="uploadForm" enctype="multipart/form-data"
    input type="file" name="attFileUpload" id="attFileUpload" class="hiddenUpload"

    label for="attAltFileName">Alternate File Name
    input type="text" id="attAltFileName" name="attAltFileName" maxlength="100"

    label for="attFileNotes" Notes
    textarea cols="50" rows="3" id="attFileNotes" name="Notes" maxlength="500"

    Any help is greatly appreciated

    ReplyDelete
    Replies
    1. As you can see in my code request.file contains fieldname (the name you are giving) and originalname (the actual diskstorage file name). You can use originalname from request.file using request.file.originalname to store it in the database.

      Delete
    2. Thanks!! Yes I was able to do that.But, I would like to access other formData/form fields in filename and destination. According to multer docs request should have it all but request.body.name always returns undefined
      Any thoughts on this? How do I get form field values from request.body in filename or destination

      Delete
  3. does it work inside routes?

    ReplyDelete