multer icon indicating copy to clipboard operation
multer copied to clipboard

Multer diskStorage destination errors on production environment

Open acho999 opened this issue 6 years ago • 17 comments

Hello,

On development environment code below works properly but on production nothing works.When I opened logs there are this error: Error OccuredError: ENOENT: no such file or directory, open 'public/images/8c3f666974_kiwi.png'.2 days I am trying to resolve it but... no result I try many things read many articles but nothing ... What is the problem?I read all multer documentation and I think I am implementing it properly?

This is code:

const express = require("express");
const router = express.Router();
const multer = require('multer');
const db = require("../connection/databaseConn");
const Product = require("../models/Product");
const encryption = require("../encryption/encryption");
const path = require('path')

let storage;
let upload;

router.get("/upload",(req,res)=>{

    res.render("upload");

});
 
let imagesNames = [];

new Promise((resolve, reject)=>{
  resolve(
    storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null,"public/images/")
  },
  filename: function (req, file, cb) {

    let imageId = encryption.generateId();
    let imageNameWithId = imageId.substr(0,10);
    imagesNames.push({name:imageNameWithId,id:imageId});
    let fileName = "" + imageNameWithId + "_" + file.originalname;

    cb(null, fileName)
  }
}))

}).then((storage)=>{
  upload = multer({storage:storage}).any();
})
  
router.post('/upload', function(req, res) {
   
    upload(req, res, function(err) {

      if(err) {
        console.log('Error Occured' + err);
          return;
        }
        let files = req.files;

        
      Product.findById(req.session.productId).then((p)=>{
          for(let i = 0; i < files.length;i++){

            p.images.push({imageId:imagesNames[i].id,imageName :"/static/images/" + imagesNames[i].name + "_"  + files[i].originalname});
                        
          }

          p.save();

      }).then(()=>{

            req.session.addMessage = "Product created!";
            res.redirect("/categoriesLoad");

       });
  })
    
});

module.exports = router;

acho999 avatar Sep 28 '18 19:09 acho999

Does the directory public/images exist?

LinusU avatar Sep 29 '18 09:09 LinusU

Yes exist, images dir is in public dir.Now I change my code to this below, but now it gives me "Internal server error: http://s1356.photobucket.com/user/acho999/media/Internal%20server%20error_zpsrmx4heor.jpg.html?sort=3&o=0

But on development again everything is working.I have images on file system and in my product object.

const express = require("express");
const router = express.Router();
const multer = require('multer');
const db = require("../connection/databaseConn");
const Product = require("../models/Product");
const encryption = require("../encryption/encryption");
const path = require('path');

router.get("/upload",(req,res)=>{

    res.render("upload");

});
 
let imagesNames = [];

const multerConfig = {
  storage : multer.diskStorage({
    destination: function (req, file, next) {
      next(null,"public/images/")
    },
    filename: function (req, file, next) {
  
      let imageId = encryption.generateId();
      let imageNameWithId = imageId.substr(0,10);
      imagesNames.push({name:imageNameWithId,id:imageId});
      let fileName = "" + imageNameWithId + "_" + file.originalname;
  
      next(null, fileName)
    }
  })
};

router.post('/upload',multer(multerConfig).any(), function(req, res) {
  
   
      let files = req.files;

      Product.findById(req.session.productId).then((p)=>{
          for(let i = 0; i < files.length;i++){

            p.images.push({imageId:imagesNames[i].id,imageName :"/static/images/" + imagesNames[i].name + "_"  + files[i].originalname});
                        
          }

          p.save();

      }).then(()=>{

            req.session.addMessage = "Product created!";
            res.redirect("/categoriesLoad");

       });
    
});

module.exports = router;

acho999 avatar Sep 30 '18 11:09 acho999

next(null,"public/images/")

Could you try returning an absolute path here? Something like:

next(null, path.join(__dirname, 'public/images'))

LinusU avatar Oct 02 '18 07:10 LinusU

Hi, thanks for helping me! I try by this way but on development environment it gives me: Error: ENOENT: no such file or directory, open 'c:\Users\Angel\Documents\Наков\JSweb\NodeAndExpress\projects\project\routes\public\images\e1ada8c985_kiwi.png'

because directory public is in directory project.In path above it search public directory in routes directory, and that is wrong. In screenshot below on left side is my Upload.js file which is on routes dir and __dirname returns path to this dir, an I think this is reason __pathname not working in this case. http://s1356.photobucket.com/user/acho999/media/error_zpsysmzjizx.jpg.html. And there is my public dir and images dir (ignore dropzone files I don't use them). Without __dirname everything works on development.When I upload image it shows in images dir.But this is only on development, on production trows error.

acho999 avatar Oct 02 '18 08:10 acho999

adjust the path to match relative to the file that holds the logic:

next(null, path.join(__dirname, '../public/images'))

LinusU avatar Oct 02 '18 14:10 LinusU

Thanks for suggestion, but again on development it works and on production return "Internal server error". As you can see on image below, in green color ,on left side, is image which I add on development environment in directory images: http://s1356.photobucket.com/user/acho999/media/dev-env_zpshjjtaivd.jpg.html. And as I wrote above on prod environment doesn't work... this is take me yet 5 days at least...

acho999 avatar Oct 02 '18 17:10 acho999

Here is screenshot of heroku logs.On the bottom where is /upload path have error, quality is not very good: http://s1356.photobucket.com/user/acho999/media/logs_zps55htwmar.jpg.html

acho999 avatar Oct 02 '18 18:10 acho999

This is error on /upload path, from heroku logs:

2018-10-03T14:29:07.566481+00:00 heroku[router]: at=info method=POST path="/upload" host=enigmatic-falls-17964.herokuapp.com request_id=74417b65-3e3d-4b70-941e-c3199325bf6c fwd="46.55.152.189" dyno=web.1 connect=0ms service=9884ms status=500 bytes=404 protocol=https 2018-10-03T14:29:07.565769+00:00 app[web.1]: Error: ENOENT: no such file or directory, open '/app/public/images/5a901a8328_IMG_20181003_142936.jpg'

acho999 avatar Oct 03 '18 14:10 acho999

Same error. Any fix?

leovazquezz1 avatar Apr 05 '19 03:04 leovazquezz1

Error: ENOENT: no such file or directory, open '/app/public/images/5a901a8328_IMG_20181003_142936.jpg'

This means that the directory /app/public/images doesn't exist, you have to create it prior to putting files in it...

LinusU avatar Apr 05 '19 10:04 LinusU

Same issue, did you figure it out?

khaled9544 avatar Jun 03 '19 20:06 khaled9544

After research, in your case you can't upload images to the server because I think you are using server-less project so from the best practices upload your images to aws s3. please checkout the following https://www.freecodecamp.org/news/express-js-and-aws-lambda-a-serverless-love-story-7c77ba0eaa35/

khaled9544 avatar Jun 03 '19 22:06 khaled9544

Same issue. Did someone figured out?

hx-gh avatar Oct 26 '20 21:10 hx-gh

Try using

destination: require.main?.path + "/" +" public/images/ "

(tested using "multer": "^1.4.2" , in typescript project)

sap-auto avatar Mar 04 '21 20:03 sap-auto

Using destination directly inside storage object without callback worked for me.

destination: path.join(__dirname, '../public/images'),

militiwari avatar Mar 05 '23 15:03 militiwari

destination: require.main?.path + "/" +" public/images/ "

This is working very well

saksham2026 avatar Dec 27 '23 09:12 saksham2026

Try using

destination: require.main?.path + "/" +" public/images/ "

(tested using "multer": "^1.4.2" , in typescript project)

This works very well, thank you.

erichutabarat avatar Jun 15 '24 07:06 erichutabarat