1

I'm using Multer together with Sharp to store images uploaded as part of an HTML form. I want to resize and transform the images before storing them on the disk and found this thread about how to do just that.

I thought I had set-up everything correctly, but when I try and upload an image I get:

Error: EISDIR: illegal operation on a directory, open 'C:\...\uploads'

Below is my code:

Routes.js:

var multer = require('multer');
var customStorage = require(path.join(__dirname, 'customStorage.js'));

var upload = multer({
    storage: new customStorage({
        destination: function (req, file, cb) {
            cb(null, path.join(__dirname, 'uploads'));
        },
        filename: function (req, file, cb) {
            cb(null, Date.now());
        }
    }),
    limits: { fileSize: 5000000 }
});
...
app.use('/upload', upload.single('file'), (req, res) => { ... });

customStorage.js:

var fs = require('fs');
var sharp = require('sharp');

function getDestination (req, file, cb) {
    cb(null, '/dev/null'); // >Implying I use loonix
};

function customStorage (opts) {
    this.getDestination = (opts.destination || getDestination);
};

customStorage.prototype._handleFile = function _handleFile(req, file, cb) {
    this.getDestination(req, file, function (err, path) {
        if (err) return cb(err);

        var outStream = fs.createWriteStream(path);
        var transform = sharp().resize(200, 200).background('white').embed().jpeg();

        file.stream.pipe(transform).pipe(outStream);
        outStream.on('error', cb);
        outStream.on('finish', function () {
            cb(null, {
                path: path,
                size: outStream.bytesWritten
            });
        });
    });
};

customStorage.prototype._removeFile = function _removeFile(req, file, cb) {
    fs.unlink(file.path, cb);
};

module.exports = function (opts) {
    return new customStorage(opts);
};
Lolechi
  • 151
  • 1
  • 3
  • 20
  • Is there any more information in the error you receive, such as a specific line where the error is being thrown? – 223seneca Feb 16 '18 at 21:18
  • Unfortunately, no. – Lolechi Feb 16 '18 at 21:19
  • Can you console log `path.join(__dirname, 'uploads')` inside the `destination` function in _Routes.js_? – 223seneca Feb 16 '18 at 21:28
  • customStorage.js: https://i.imgur.com/EDO7Wgm.png Routes.js: `Path: C:\Users\lolechi\Desktop\nosos\public\rooms` I lied a little and said that the images are uploaded to `uploads` but they're actually uploaded to `public\rooms`. – Lolechi Feb 16 '18 at 21:32
  • Does this directory already exist before you run the code? If so, try changing the path name to a directory that doesn't exist (maybe `C:\Users\lolechi\Desktop\nosos\public\uploads`) and see if it works. I _think_ Multer requires that it creates a new directory as it runs. – 223seneca Feb 16 '18 at 21:35
  • Also make sure the path has a `/` at the end, just in case (that's what they do in the Multer docs). – 223seneca Feb 16 '18 at 21:37
  • I deleted the `rooms` directory and Multer just created a file called `rooms` that was the uploaded image. I think the problem is that the path being passed doesn't include the desired filename. – Lolechi Feb 16 '18 at 21:38
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/165310/discussion-between-223seneca-and-lolechi). – 223seneca Feb 16 '18 at 21:38

1 Answers1

1

The error Error: EISDIR: illegal operation on a directory in this context indicates that you are setting Multer's destination to a directory when it should be the name of the destination file.

The destination is set in the line cb(null, path.join(__dirname, 'uploads')); in Routes.js. If you change this line to something like cb(null, path.join(__dirname, 'myDirectory\\mySubdirectory\\', myFilename + '.jpg')), it will work.

223seneca
  • 1,136
  • 3
  • 19
  • 47