0

I'm trying to make a sign up form with an image upload ability so I take the values on the ejs side using this by a post and enctype = "multipart/form-data"

<form method="post" action= "/SignUp" enctype="multipart/form-data" >
    <div class="form-group">
        <label for="firstName">First name</label>
        <input type="text" name="firstName" id="firstName" class="form-control" value="<%= locals.firstName || '' %>" required />
    </div>
    <div class="form-group">
        <label for="lastName">Last name</label>
        <input type="text" name="lastName" id="lastName" class="form-control" value="<%= locals.lastName || '' %>" required />
    </div>
    <div class="form-group">
        <label for="username">Username</label>
        <input type="text" name="username" id="username" class="form-control" value="<%= locals.username || '' %>" required />
    </div>
    <div class="form-group">
        <label for="password">Password</label>
        <input type="password" name="password" id="password" class="form-control" required />
    </div>
    <div class = "from-group">
      <label for = "Image">Image</label>
      <input Content-Type = "multipart/form-data" type ="file" name = "Image" id = "Image" class = "form-control" required/>
    </div
    <br />
    <br />
    <div class="form-group">
        <button type="submit" class="btn btn-primary">Register</button>
        <a href="/login" class="btn btn-link">Cancel</a>
    </div>
</form>

and I handle it from the server side using busboy

  SignUp:function(req,res){
  let reg = new Registrations();
  var busboy = new Busboy({
    headers: req.headers,
    limits: {
      fileSize: 6*1024*1024 //2MB limit
    }
  });
    var stream;
    var fstream;
       busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated) {
         if(fieldname == 'firstName')
         reg.firstName = val;
         else if (fieldname == 'lastName')
          reg.lastName = val;
          else if(fieldname == 'username')
          reg.username = val;
          else {
            reg.password = val;
          }


       })
      busboy.on('file', function(fieldname,file, filename,encoding,mimeType){
      stream = __dirname + '/img/' + filename;
      fstream = fs.createWriteStream(__dirname + '/img/' + filename);
      file.pipe(fstream);
      fstream.on('close', function(){
          reg.Image = stream;
        reg.save(function(err,reg){
          if(err){
            res.send(err.message)
            console.log(err);
          }else{
            console.log(reg);
          }
        })
      })
    })
    busboy.on('finish', function() {

    })
    res.render('login');

  }

it shows me this error every time I try it
TypeError: Cannot read property 'on' of undefined on the line

req.busboy.on('file', function(fieldname,file, filename,encoding,mimeType)

Can you please tell me what is this problem about ?

ultimate_beaver
  • 85
  • 2
  • 12

3 Answers3

0

After a first look into the busboy-doc, it seems to me, as busboy is no middleware, which is extending the request, see the code snippet:

var busboy = new Busboy({ headers: req.headers });
    busboy.on('file',...
Myonara
  • 1,197
  • 1
  • 14
  • 33
0

I have previously used busboy to upload images and I will share with you the configs and how its done.

  1. Import the busboy module

    var Busboy = require('busboy');

  2. Then inside your post endpoint declare busboy object

    var busboy = new Busboy({
      headers: req.headers,
      limits: {
        fileSize: 6*1024*1024 //2MB limit
      }
    });
    
  3. Followed by the rest of the code inside the post endpoint

    busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated) {
           //extract intput-field from upload-form
    });
    
    
    busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
          //process each file upload, check for size, mimetype, 
          //store if all checks passed, delete otherwise, move to 
          //next file
    });
    
    
    //finish call back when all files are uploaded
    busboy.on('finish', function() {
        //do cleanup and other related work 
    });
    
    return req.pipe(busboy);
    

I have created a gist off the project where I used busboy for uploading multiple images with following checks

  1. Extract the input fields from the upload form
  2. Make sure that file size is not over specified XMB
  3. Make sure that the mimetypes are valid
  4. As soon as a file is found with over XMB (X.1MB) then abort the upload and move to the next file
  5. If file satisfies all checks then store it locally

Here is the link to the public gist Upload Multiple Files with Busboy Nodejs ExpressJS

Raf
  • 7,505
  • 1
  • 42
  • 59
  • what is the on('field',...) for ? – ultimate_beaver Feb 26 '17 at 20:47
  • that's the callback that will extract the input fields of the upload form, basically any field that is not of type file (i.e. firstName, lastName, etc.) – Raf Feb 26 '17 at 20:50
  • I adapted my module based on yours. The error is gone, but it's not even receiving the fields now ( firstName, etc....). Do you think I'm handling it correctly from the html side ? I edited my question's code if you want to have a look – ultimate_beaver Feb 26 '17 at 21:21
  • can you put some console logs to see whether the **on field** is invoked or not? if yes invoked then what is the value of the **fieldname** for which its invoked. As long as in your form the input fields are before the file field, it should be accessible. – Raf Feb 26 '17 at 21:25
0

I used multer instead and it worked correctly

https://github.com/expressjs/multer

ultimate_beaver
  • 85
  • 2
  • 12