multer saves image in a weird format - node.js

I am trying to serve an image from my Express server to my client but multer is saving the file in a weird format which leads to issues when my react app tries to render the image
multer server side code:
const fileFilter = (req, file, cb) => {
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png'){
// accept a file
cb(null, true);
} else {
// reject a file
cb(new Error('Incorrect file'), false);
}
}
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/');
},
filename: (req, file, cb) => {
cb(null, Date.now() + path.extname(file.originalname))
}
});
const upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 5 // max 5mb for image size
},
fileFilter: fileFilter
});
router.post('/', upload.single('productImage'), ProductsController.products_create_product);
This code successfully creates the file in the /uploads folder but when I save the path to the database I get this response:
Postman
{
"size": 5,
"quantityInStock": 11,
"productImage": "uploads\\2021-03-11T19-18-05.442Zvans-2.jpg",
}
How can I change it so it saves the image in this format: /uploads/2021-03-11T19-18-05.442Zvans-2.jpg

You just need to fix your destination path like this:
cb(null, path.join(__dirname, './uploads/'));
For me this was the full code-block. Just grab the actual part you want:
const multer = require('multer');
const path = require('path');
const appConfigs = require('./../config/app');
module.exports = function (folderName) {
// TODO: console log here and optimize multiple initialization of multer if need
return multer({
storage: multer.diskStorage({
destination: function (req, file, cb) {
const filePath = path.join(__dirname, './../uploads/' + folderName);
cb(null, filePath);
},
filename: function (req, file, cb) {
const extension = file.mimetype.split('/')[1];
const fileName = (new Date().getTime() / 1000 | 0) + '.' + extension;
cb(null, fileName);
}
}),
limits: {
fileSize: 1024 * 1024 * appConfigs.image_max_size // MB
},
fileFilter: (req, file, cb) => {
let valid = (file.mimetype === 'image/jpeg' || file.mimetype === 'image/jpg' || file.mimetype === 'image/png');
cb(null, valid);
},
});
};

Related

Upload/Store multiple files with multer, i.e image and pdf with single request in nodejs

The following code works to upload a single image to upload an image and store its path in the database, now I can't find a way to upload an image and a pdf file in a single request and also store their paths in the database. I need to upload both of them when I create the user.
user-routes.js
const express = require("express");
const router = express.Router();
const { getUser, createUser } = require("./user-controller");
const multer = require("multer");
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "./uploads/");
},
filename: function (req, file, cb) {
cb(null, new Date().toISOString().replace(/:/g, "-") + file.originalname);
},
});
const fileFilter = (req, file, cb) => {
if (
file.mimetype === "image/jpeg" ||
file.mimetype === "image/png" ||
file.mimetype === "image/jpg"
) {
cb(null, true);
} else {
cb(null, false);
}
};
const upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 25,
},
fileFilter: fileFilter,
});
router.post("/", upload.single("userImage"), async (req, res) => {
const newUser = await User.create({ ...req.body, userImage: req.file.path });
console.log(req.file);
res.send("CREATE USER");
};);
user-model.js
const userSchema = new mongoose.Schema({
name: String,
job: String,
userImage: String,
userDoc: String,
});

is there any option for upload indexed image file in multer postman nodejs express?

Like i have send indexed array for multiple product.
MulterError: Unexpected field
at wrappedFileFilter (E:\projects\Dlsali\node_modules\multer\index.js:40:19)
1.middleware
import multer from "multer";
// const upload = multer({ dest: './../uploads/' })
import { envs } from "../config/index.js";
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads/product_image')
},
filename: function (req, file, cb) {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
return cb(null, uniqueSuffix + '-' + file.originalname)
}
})
const fileFilter = (req, file, cb) => {
if (
file.mimetype === "image/jpg" ||
file.mimetype === "image/jpeg" ||
file.mimetype === "image/png"
) {
cb(null, true);
} else {
return cb({ code: "LIMIT_FILE_TYPE" });
}
};
// function for upload file
export const uploadSingleProductImage = multer({
storage: storage,
limits: { fileSize: 1024 * 1024 * 10 },
fileFilter: fileFilter,
});
Router
postsRouter.post("/create-post",
validateAccessToken,
uploadFile.array('post_images', 10),
uploadSingleProductImage.array('products',13),
postCreateValidate.postCreateValidate,
postsController.create
);

Multer is not processing file upload in typescript-node.js

import multer, { FileFilterCallback } from "multer";
import { Request } from "express";
import { randomBytes } from "crypto";
const fileStorage = multer.diskStorage({
destination: (req: Request, file: Express.Multer.File, cb) => {
// if I add absolute path for "images", it would be stored in db as absolute, so when I retrieve the path for the <img src=""/> src would not accept because it requires "/images/
cb(null, "images");
},
filename: (req, file, cb) => {
cb(null, randomBytes(4).toString("hex") + "-" + file.originalname);
},
});
const fileFilter = (
req: Request,
file: Express.Multer.File,
cb: FileFilterCallback
) => {
if (
file.mimetype === "image/png" ||
file.mimetype === "image/jpg" ||
file.mimetype === "image/jpeg"
) {
cb(null, true);
} else {
cb(null, false);
}
};
app.use(bodyParser.urlencoded({ extended: false }));
app.use(multer({ storage: fileStorage, fileFilter }).single("image"))
Same code was working for js but when I converted to Typescript, it breaks. when I submit the form, it is spinning, means multer is not passing it to next middleware.
When I pass absolute path it works, but the issue with absolute path, it will save the absolute path to the database and when I retrieve it <img src="/home/..."> absolute path will be returned and it won't display the image:
const mainFile = path.dirname(process!.mainModule!.filename);
const imagesPath = path.join(mainFile, "images");
const fileStorage = multer.diskStorage({
destination: (req: Request, file: Express.Multer.File, cb) => {
cb(null, imagesPath);
},
filename: (req, file, cb) => {
cb(null, randomBytes(4).toString("hex") + "-" + file.originalname);
},
});
I edited ts.config.json but still get that error:
"baseUrl": "./src"

fileFilter on multer still allowing all file types

Added a fileFilter to my storage function allowing only image file types to be uploaded, but all file types are still being uploaded.
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/profilePictures')
},
filename: function (req, file, cb) {
cb(null, `${Date.now()}_${file.originalname}`)
},
fileFilter: (req, file, cb) => {
const ext = path.extname(file.originalname).toLower()
if (ext !== '.jpg' || ext !=='.png' || ext !== '.jpeg') {
return cb(res.status(400).end('Error only photos can be uploaded'), false);
}
cb(null,true)
}
})
var upload = multer({ storage: storage }).single("file")
Here's a way to do it using regex:
fileFilter: (req, file, cb) => {
const filetypes = /jpeg|jpg|png|gif/;
const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
const mimetype = filetypes.test(file.mimetype);
if (mimetype && extname) return cb(null, true);
else cb("Error: Images Only!");
}

Double backslash into path

I have using this the tuttorial of Academind how to load image using multer into node JavaScript rest service.
About path destination folder I use this code:
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, './uploads/');
},
filename: function(req, file, cb) {
cb(null, file.originalname);
}
});
const fileFilter = (req, file, cb) => {
// reject a file
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true);
} else {
cb(null, false);
}
};
const upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 5
},
fileFilter: fileFilter
});
But the path generated have double backslash that show as one backslash:
uploads\2018-09-16T13-02-45.535Z1536685465dummy4.jpg
How I can replace destination path with slash?
i had the same issue, and since i didn't find anything i did this as a work around
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads/');
},
filename: function (req, file, cb) {
cb(null, `${new Date().toISOString().replace(/:/g, '-')}${file.originalname.split(" ").join("_")}`);
}
});
const user= new User({
_id : new mongoose.Types.ObjectId(),
name : req.body.name,
image: req.file.destination + req.file.filename,
});

Resources