Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Expressjs: ENOENT when uploading image

Expressjs: ENOENT when uploading image

Problem

I have written some middleware for uploading an Avatar, like this:

var gm = require('gm'),
    mkdirp = require('mkdirp'),
    fs = require('fs');

uploadAvatar = function(req, res, next) {
  var img, path, user;
  if (req.files.avatar_image) {
    user = req.user;
    img = req.files.avatar_image;
    path = __dirname + "/../../public/avatar/" + (user.name.parameterize()) + ".png";
    mkdirp.sync(__dirname + "/../../public/avatar/");
    fs.createReadStream(img.path).pipe(fs.createWriteStream(path));
    gm(path).resize(250, 250).autoOrient().quality(90).write(path, function(err) {
      if (err != null) {
        req.flash('error', err);
      } else {
        user.avatar = "/avatar/" + (user.name.parameterize()) + ".png";
        user.save(function(err) {
          if (err != null) {
            req.flash('error', err);
          }
          next();
        });
      }
    });
  } else {
    next();
  }
};

// Usage
app.post('/upload', ensureAuthenticated, uploadAvatar, handleUpload);

When I now try to upload an image, node crashed with the incredibly helpful error message:

events.js:72
    throw er; // Unhandled 'error' event
          ^
Error: ENOENT, open '/tmp/1126846a248af5c584770b07de649f9b.png'

I have tried copying the file before using gm on it, too. I suspect that express deletes the file before I can even touch it, as a "security".

Can anyone help me here?

EDIT: Full source

Problem courtesy of: Lanbo

Solution

First of all copy temp file to your avatar directory, and second make sure that you have permissions on avatar as well as temp directory and files.

As well piping read to write stream is not sync operation, and you will try to pipe straight after initialising read handle, that might lead to some problems.
You need to add events and wait till file get copied:

var complete = function(err) {
  if (!err) {
    // process your gm
  } else {
    console.log(err);
  }
}

var read = fs.createReadStream(sourcePath);
read.on('error', function(err) {
  complete(err);
});

var write = fs.createWriteStream(targetPath);
write.on('error', function(err) {
  complete(err);
});
write.on('close', function() {
  complete();
});
read.pipe(write);
Solution courtesy of: moka

Discussion

View additional discussion.



This post first appeared on Node.js Recipes, please read the originial post: here

Share the post

Expressjs: ENOENT when uploading image

×

Subscribe to Node.js Recipes

Get updates delivered right to your inbox!

Thank you for your subscription

×