Expressjs file upload using Multer is not working After Nginx proxy

28 Views Asked by At

I have deployed my MERN (MongoDB, Express.js, React.js, Node.js) application to a VPS (Virtual Private Server) and configured Nginx to serve it. In my local development environment, I can successfully add a product with an image upload feature. However, when I attempt to do the same in production, I encounter a 400 Bad Request error.

In my production environment, the PM2 logs show the following error during image upload:

Image upload error: [Error: ENOENT: no such file or directory, open 'public/uploads/products/image-1710418885258.png'] code: 'ENOENT', syscall: 'open', path: 'public/uploads/products/image-1710418885258.png'

Nginx configuration:

server {
  listen 80;
  server_name ;

  location / {
    root /var/www/vital/Client;
    index  index.html index.htm;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
    try_files $uri $uri/ /index.html;
  }

  location /api/v1/ {
    client_max_body_size 500M;
    proxy_pass http://(vps-ip-address):3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
  }
}

Multer configuration:

const multerStorage = multer.diskStorage({
  filename: (req, file, cb) => {
    cb(
      null,
      file.fieldname + "-" + Date.now() + path.extname(file.originalname)
    );
  },
  destination: (req, file, cb) => {
    cb(null, "/public/uploads/products");
  },
});

const upload = multer({
  storage: multerStorage,
});

exports.uploadProductImage = (req, res, next) => {
  upload.single("image")(req, res, (err) => {
    if (err) {
      console.error("Image upload error:", err);
      return res.status(400).json({
        status: "error",
        message: "Image upload failed",
      });
    }
    next();
  });
};

exports.createProduct = catchAsync(async (req, res) => {
  const productData = {
    name: req.body.name,
    description: req.body.description,
    category: req.body.category,
    trending: req.body.trending,
    subCategory: req.body.subCategory || null,
    tags: req.body.tags,
    productImage: req.file.filename,
  };
  const newDoc = await Product.create(productData);
  setTimeout(() => {
    res.status(201).json({
      status: "success",
      data: {
        newDoc,
      },
    });
  }, 1000);
});

Router configuration and mounting:

app.use("/api/v1/products", productRouter);
router
  .route("/create-products")
  .post(productController.uploadProductImage, productController.createProduct);

The file upload works well on my local machine but doesn't work in production. I've ensured that the file path specified in the multer configuration matches the actual directory structure on the VPS. The Nginx configuration seems correct for proxying requests to the Node.js server. Are there any other issues or configurations that I might be missing?

0

There are 0 best solutions below