How to save details in MongoDb along with image - node.js

I want to save details in mongodb and image in images folder using multer, but I am not getting data in the server
const onSubmit=async(object) =>{
const fd = new FormData()
fd.append('name', object.name)
fd.append('category', object.category)
fd.append('quantity', object.quantity)
fd.append('price', object.price)
fd.append('myFile',object.file[0], object.file[0].name)
const response = await axios.post(`${url}/admin/add-product`,fd)
}
model
name:String,
category:Number,
quantity:Number,
price:Number,
image:String
server
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'images')
},
filename: function (req, file, cb) {
cb(null, Date.now() + '-' +file.originalname )
}
})
``
const upload = multer({ storage: storage })
route.post('/admin/add-product',upload.single('myFile'),addProduct)
export const addProduct = async (req, res)=>
{
try{
}catch(error)
{
res.status(404).json({message:error.message})
}
}

const url = `http://localhost:2001`
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'images')
},
filename: function (req, file, cb) {
cb(null, file.originalname )
}
})
route.post('/admin/add-product',upload.single('file'), addProduct)
const addProduct = async (req, res)=>
{
try{
const object = {name:req.body.name,category:req.body.category,quantity:req.body.quantity,price:req.body.price,image:req.file.filename }
if(!req.file)
return res.status(404).json('image not found')
const imageUrl = `${url}/admin/add-product/${req.file.filename}`
const newProduct = new Product(object)
await newProduct.save()
return res.status(201).json(imageUrl)
}catch(error)
{
res.status(404).json({message:error.message})
}
}

Related

How can I upload images at different models

I want my images to be separated...it doesn't upload the file in the file location that I wanted but it is saving at my mongoose..Here's the code for my routes
const multer = require('multer');
const { v4: uuidv4 } = require('uuid');
let path = require('path');
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null,'./apples/accessories')
cb(null, '../public/uploads');
},
filename: function(req,file,cb) {
let ext = path.extname(file.originalname)
cb(null, uuidv4() + '-' + Date.now() + ext)
}
});
const storage2 = multer.diskStorage({
destination: function(req, file, cb) {
cb(null,'./apples/ipad')
cb(null, '../public/uploads');
},
filename: function(req,file,cb) {
let ext = path.extname(file.originalname)
cb(null, uuidv4() + '-' + Date.now() + ext)
}
});
const fileFilter = (req, file, cb) => {
const allowedFileTypes = ['image/jpeg', 'image/jpg', 'image/png'];
if(allowedFileTypes.includes(file.mimetype)) {
cb(null, true);
} else {
cb(null, false);
}
}
const fileFilter2 = (req, file, cb) => {
const allowedFileTypes = ['image/jpeg', 'image/jpg', 'image/png'];
if(allowedFileTypes.includes(file.mimetype)) {
cb(null, true);
} else {
cb(null, false);
}
}
let upload = multer({ storage, fileFilter });
let upload2 = multer({ storage2, fileFilter2 });
router.route('/create').post(upload.single('image'),createAppleAcc)
router.route('/create2').post(upload2.single('image'),createAppleIpad)
And this is my controller
const createAppleAcc = (req,res) => {
const { itemname,itemno } = req.body
const image = req.file.originalname
const newAcc = new Accessories({
itemname,itemno,image
})
newAcc.save()
.then(data => res.send('Create successful Accessories'))
.catch(data => console.log(data))
}
const createAppleIpad = (req,res) => {
const { itemname,itemno } = req.body
const image = req.file.originalname
const newAcc = new Ipad({
itemname,itemno,image
})
newAcc.save()
.then(data => res.send('Create successful Ipad'))
.catch(data => console.log(data))
}
This actually works but I don't know why the upload2 don't work..it doesn't save in my file location as I wanted but the upload is working very well..Do you guys have any idea how this thing works? I already tried to create a new upload and a new storage as you can see as upload2 and storage2 and fileFilter2. Where is the part I am wrong??

Expressjs multer middleware save file in dynamic destination

I am using multer with expressjs and I am trying to change the DIR to save images depending on the request to a dynamic destination, my code is working fine but always save images inside the post directory, I'm using this middleware with multi requests.
1- How can I make the directory dynamic! example: to save to ./public/products if req product & save to ./public/posts if req post
2- How to make sure that the file is uploaded to the directory with no errors in the controller! then save the path to the database!
3- Is this the best practice to use multer ! in middleware level!
multer middleware fileUpload.js
const multer = require("multer");
const mkdirp = require("mkdirp");
const fs = require("fs");
const getDirImage = () => {
// const DIR = './public/uploads/products';
return `./public/posts`;
};
let storage = multer.diskStorage({
destination: (req, file, cb) => {
console.log(req.params,'&&&&&&&&&&&&',file);
let DIR = getDirImage();
if (!fs.existsSync(DIR)) {
fs.mkdirSync(DIR, { recursive: true });
}
cb(null, DIR);
},
filename: (req, file, cb) => {
const fileName = "overDress" + Date.now() + "" +
file.originalname.toLowerCase().split(' ').join('-');
cb(null, fileName)
},
});
const upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 10 //upto 2 megabytes per file.
},
fileFilter: (req, file, cb) => {
if (file.mimetype == "image/png" || file.mimetype == "image/jpg" ||
file.mimetype == "image/jpeg") {
cb(null, true);
} else {
cb(null, false);
return cb(new Error('File types allowed .jpeg, .jpg and .png!'));
}
}
});
module.exports = upload;
product.js route
const controller = require('../controllers/product.controller');
import { Router } from 'express'; //import from esm
import upload from '../middleware/fileUpload'
const router = Router();
router
.get('/', controller.list)
.post('/', upload.single('image'), controller.create)
.get('/:id', controller.getOne)
export default router;
and my create controller:
exports.create = async (req, res, next) => {
const { name, title, description,subtitle} = req.body;
if (!name || !title) {
return res.status(400).send({
message: 'Please provide a title and a name to create a product!',
});
}
try {
if (req.file) {
req.body.image = req.file.destination + '/' + req.file.filename;
}
const PRODUCT_MODEL = {
name: req.body.name,
title: req.body.title,
description: req.body.description,
image: req.body.image,
};
try {
const product = await Product.create(PRODUCT_MODEL);
console.log('product crerated');
return res.status(201).json(product);
} catch (error) {
console.log(error);
return res.status(500).send({
message: 'Something went wrong: ' + error,
});
}
} catch (error) {
return res.status(500).json(error);
}
};

How to upload an image with multer to Google Cloud in Express js

I have an issue, I succeed to upload a picture to a folder, but how to upload to Google Cloud?
Here is my code:
const multer = require('multer');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads/');
},
filename: function (req, file, cb) {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
const original = file.originalname; //original name yg di upload
const ext = original.substr(original.length - 5);//ambil 5 string terakhir pasti itu sudah termasuk extension
const regex = /[^\w\s]/g;//temukan selain word/kata atau whitepsace
const dot = ext.search(regex);
cb(null, uniqueSuffix + ext.substr(dot));//ambil setelah . sebagai extension
}
});
const fileFilter = (req, file, cb) => {
// jika jpg dan png maka di terima, selain itu riject
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true);
} else {
cb(null, false);
}
}
upload_image = multer({
storage: storage,
limits: {fileSize: 1024 * 1024 * 5},
fileFilter: fileFilter
});
module.exports = upload_image;
What I need is only change/upload to Google Cloud.
Thank you in advance!
finally i found the solution
the basic idea is, first i upload picture to /upload folder, after that i upload from /upload to google cloud, last i delete file in /upload folder, but for delete i put in the end of middle ware cause if delete after upload to google cloud, file is deleted before upload to google cloud finish
this my complete code
upload to /upload folder
const multer = require('multer');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads/');
},
filename: function (req, file, cb) {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
const original = file.originalname; //original name yg di upload
const ext = original.substr(original.length - 5);//ambil 5 string terakhir pasti itu sudah termasuk extension
const regex = /[^\w\s]/g;//temukan selain word/kata atau whitepsace
const dot = ext.search(regex);
cb(null, uniqueSuffix + ext.substr(dot));//ambil setelah . sebagai extension
}
});
const fileFilter = (req, file, cb) => {
// jika jpg dan png maka di terima, selain itu riject
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true);
} else {
cb(null, false);
}
}
upload_image = multer({
storage: storage,
limits: {fileSize: 1024 * 1024 * 5},
fileFilter: fileFilter
});
module.exports = upload_image;
this is code to upload to google cloud
const util = require('util')
const gc = require('../../config')
const bucket = gc.bucket('mybucket')//bucket name di google drive
const path = require('path')
const { format } = util
//promise di panggil di midleware
const uploadImage = (files) => new Promise((resolve, reject) => {
//perlu di looping di sini karena yang di kirim berupa array
let arrayPicture = [];
files.forEach(element => {
const {filename} = element
// console.log(filename);
const picture = path.join(__dirname,'../../uploads',filename);
//ini peruntah untuk uplaod
bucket.upload(picture);
// ini yang di kirim ke return
// const publicUrl = format(
// `https://storage.googleapis.com/${bucket.name}/${filename}`
// )
arrayPicture.push(picture);
});
resolve(arrayPicture);
reject(err=>(err))
})
module.exports = uploadImage
this is my code to delete in /upload folder
const fs = require('fs');
module.exports = (req,res,next)=>{
// const arrayPicture = req.picture;
const removeImage = (arrayPicture)=> new Promise( (resolve,rejects)=>{
arrayPicture.forEach(element => {
fs.unlink(element,(err)=>{
if(err){
console.log(err);
res.status(500).json({
message:"remove data from folder fail",
error: err, status:500,
});
}
});
});
const message = "unlink succed"
resolve(message);
rejects(err=>(err))
});
removeImage(req.picture)
.then(result=>{
// res.send(result);
next();
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err, status:500, message:"unlink unsucced"
});
})
}
please note that i send array of picture name in req.picture with location directory
and this is my route midleware
router.post("/", checkAuth, checkProfile, UploadService.array('productImage',4), PostImageToCloud
,ProductPostController,ProductQuantityPostController ,ProductImagePostController ,RemoveImageWasUpload
,ProductResource);

multer create folder if not exist

I saw in documentation of multer, that if folder doesn't exist, the multer will not create folder. How can i create a folder if not exist?
import multer from 'multer'
import crypto from 'crypto'
import { extname, resolve } from 'path'
import slug from 'slug'
export default {
storage: multer.diskStorage({
destination: resolve(__dirname, '..', '..', 'uploads', 'gallery'),
filename: (req, file, cb) => {
const { id, description } = req.body
crypto.randomBytes(8, (err, res) => {
if (err) return cb(err)
return cb(null, id + '/' + res.toString('hex') + '/' + slug(description, { lower: true }) + extname(file.originalname))
// return cb(null, res.toString('hex') + extname(file.originalname))
})
}
})
}
i had change to:
import multer from 'multer'
import crypto from 'crypto'
import { extname } from 'path'
import slug from 'slug'
import fs from 'fs'
export default {
storage: multer.diskStorage({
destination: (req, file, cb) => {
const { id } = req.body
const path = `./uploads/gallery/${id}`
fs.mkdirSync(path, { recursive: true })
return cb(null, path)
},
filename: (req, file, cb) => {
const { description } = req.body
crypto.randomBytes(3, (err, res) => {
if (err) return cb(err)
return cb(null, slug(description, { lower: true }) + '_' + res.toString('hex') + extname(file.originalname))
})
}
})
}
I have done it in this way, and it works fine for me. so you can try. hopefully it will work for you. good luck
#########controller##########
// image Upload
const multer = require('multer')
const path = require('path')
const fs = require("fs");
const storage = multer.diskStorage({
destination: (req, file, cb) => {
balayAudPath = 'media/content/agriInput/balay/audio'
fs.mkdirSync(balayAudPath, { recursive: true })
cb(null, balayAudPath)
},
filename: (req, file, cb) => {
cb(null, Date.now() + path.extname(file.originalname))
}
})
const upload = multer({
storage: storage
}).fields([
{ name: 'contentAudio', maxCount: 1 }
])
//.single('imageFile');
// .array('images', 3) //| for upload multiple files
module.exports = {
upload
}
router
xxxRouterWeb.post('/addXXXAudio', auth,
xxxController.upload, xxxController.addBalayAudio)

Generate destination path before file upload - multer

Trying to make a folder before uploading a file to it. However, there is a problem if I do not update the server on the node when I try to download the file again, it is added to the already created folder. If I update the server, it creates a new folder and uploads it as needed. Please see the code, how can I improve it?
const db = require('../db');
const fs = require('fs');
const path = require('path');
const uuidv1 = require('uuid/v1');
const multer = require('multer');
console.log(uuidv1())
let storage = multer.diskStorage({
destination: `./uploads/${uuidv1()}`,
filename: (req, file, cb) => {
cb(null, 'test1' + '-' + Date.now() + '.' + path.extname(file.originalname));
}
});
let upload = multer({storage});
module.exports = (router) => {
router.get('/get', (req, res) => {
db.connect.query('SELECT * FROM habalka',
{type: db.sequelize.QueryTypes.SELECT}
).then(result => {
res.json(result);
})
});
router.post('/post', upload.any(), (req, res) => {
res.json('test');
});
return router;
};
Your issue is that when You start Your app it generates new uuid (once - at app startup) and passes as string to diskStorage method.
But You want to generate that path every-time when You upload a file.
So here is the solution:
Multer has feature to dynamically generate both destination path and filename.
So You've to pass a function that will generate path and return it in callback.
Example after reading this manual:
let storage = multer.diskStorage({
// pass function that will generate destination path
destination: (req, file, cb) => {
// initial upload path
let destination = path.join(__dirname, 'uploads'); // ./uploads/
// if user logged in and You store user object in session
if (req.session && req.session.user && req.session.user.id) {
destination = path.join(destination, 'users', req.session.user.id, uuidv1()); // ./uploads/users/8/generated-uuid-here/
}
else {
destination = path.join(destination, 'files', uuidv1()); // ./uploads/files/generated-uuid-here/
}
cb(
null,
destination
);
},
// pass function that may generate unique filename if needed
filename: (req, file, cb) => {
cb(
null,
Date.now() + '.' + path.extname(file.originalname)
);
}
});
My final code is here and it works !Thanks
const db = require('../db');
const fs = require('fs');
const uuid = require('uuid');
const path = require('path');
const multer = require('multer');
const shell = require('shelljs');
console.log(uuid())
let storage = multer.diskStorage({
// pass function that will generate destination path
destination: (req, file, cb) => {
// initial upload path
let destination = path.join(__dirname, '../uploads'); // ./uploads/
let id = uuid();
shell.mkdir('-p', './uploads/' + id);
destination = path.join(destination, '', id); // ./uploads/files/generated-uuid-here/
console.log('dest', destination)
cb(
null,
destination
);
},
// pass function that may generate unique filename if needed
filename: (req, file, cb) => {
let ext = file.originalname.substring(file.originalname.lastIndexOf('.'), file.originalname.length);
callback(null,file.originalname.split('.').slice(0,-1).join('.') + '-'+Date.now() +ext);
}
});
var upload = multer({storage: storage})
module.exports = (router) => {
router.get('/get', (req, res) => {
db.connect.query('SELECT * FROM habalka',
{type: db.sequelize.QueryTypes.SELECT}
).then(result => {
res.json(result);
})
});
app.post('/uploads', function (req, res) {
upload(req, res, function (err) {
if (err) {
console.log(err);
return res.end("Something went wrong!");
}else{
let ext = req.file.originalname.substring(req.file.originalname.lastIndexOf('.'), req.file.originalname.length);
var files='./uploads/'+req.file.originalname.split('.').slice(0 ,-1).join('.')+'-'+Date.now()+ext
console.log(req.file.originalname);
collection.insertOne({files},function(err,result){
if(err){
console.log("Something is Wrong");
}else{
res.json(result._id);
console.log(result);
}
})
}
});
})
return router;
};
In your multer middleware, you can do something like:
import util from "util";
import multer from "multer";
export const maxSize = 20 * 1024 * 1024;
export const __upoads_folder='/volume1/server/dash_rental_server/uploads';
let uploadFile = multer({
storage: multer.diskStorage({
destination: (req, file, cb) => {
const fileName = req.params.name;
let directoryPath = __upoads_folder + "/";
if (req?.params?.folder) { directoryPath += req.params.folder + '/' };
if (req?.params?.category) { directoryPath += req?.params?.category + '/' };
cb(null, directoryPath);
},
filename: (req, file, cb) => {
console.log(file.originalname);
cb(null, file.originalname);
},
}),
limits: { fileSize: maxSize },
}).single("file");
export let uploadFileMiddleware = util.promisify(uploadFile);
Then, in your route:
router.post("/upload/:folder/:category", async (req, res) => {
try {
await uploadFileMiddleware(req, res);
if (req.file == undefined) {
return res.status(400).send({ message: "Please upload a file!" });
}
res.status(200).send({
message: "Uploaded the file successfully: " + req.file.originalname,
});
} catch (err) {
if (err.code == "LIMIT_FILE_SIZE") {
return res.status(500).send({
message: `File size cannot be larger than ${maxSize / 1024 / 1024} MB!`,
});
}
res.status(500).send({
message: `Could not upload the file: ${req.file.originalname}. ${err}`,
});
}
});

Resources