How can I upload images at different models - node.js

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??

Related

How to save details in MongoDb along with image

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})
}
}

NodeJS / Multer : How to replace exising file in directory with new file

I want to replace existing file in directory when upload new new , I'm using nodeJS and multer, the idea is to read directory content, delete it and then upload the new file.
const express = require('express')
const router = express.Router()
const authorize = require('_middleware/authorize')
const Role = require('_helpers/role')
const uploadImage = require("./uploadAdvertising")
const fs = require('fs')
const uploadDir = '/public/advertising/'
// routes
router.post('/', authorize(Role.Admin), uploadImage, createAdvertising);
module.exports = router;
async function createAdvertising(req, res, next) {
fs.readdir(global.__basedir + uploadDir, ((err, files) => {
if (err) throw err
for (const file of files){
fs.unlink(global.__basedir + uploadDir + file, err => {
if (err) throw err;
});
}
}))
if (!req.file) return res.status(412).send({
message: `image is required`,
});
uploadImage(req, res)
.then(data => {
return res.status(201).send({
message: 'Advertising image saved'
})
}).catch(err => {
return res.status(500).send({
message: `Could not upload the file, ${err}`,
});
})
}
multer
const util = require("util");
const multer = require("multer");
const maxSize = 10 * 1024 * 1024;
const uploadDir = '/public/advertising/'
const fs = require('fs')
let storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, global.__basedir + uploadDir)
req.uploadDirectory = global.__basedir + uploadDir
},
filename: (req, file, cb) => {
cb(null, file.originalname)
},
});
let uploadImage = multer({
storage: storage,
fileFilter: (req, file, cb) => {
//reject
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true)
} else {
cb(new Error("image should be png or jpeg extension"), false)
}
},
limits: {fileSize: maxSize},
}).single("imageAdvertising");
let uploadFileMiddleware = util.promisify(uploadImage);
module.exports = uploadFileMiddleware;
can some one take a look and tell what's wrong with this code ! it delete all content even the new uploaded file !
just try like this in the multer file
note : write the path of uploaded file in unlinkSync and readdirSync
fileFilter: (req, file, cb) => {
let files = fs.readdirSync('write the path');
if(files.includes(file.originalname)){
fs.unlinkSync('pwrite the pathath'+ file.originalname);
}
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true)
} else {
cb(new Error("image should be png or jpeg extension"), false)
}
}
and remove extra code like createAdvertising file

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);

Handle destination per route in nodejs with multer package

I use multer package and make it dynamic and its work. Now it try to make it dynamic per route and stuck with this.
This is my fileupload service:
const path = require("path");
const multer = require("multer");
const crypto = require("crypto");
const fs = require("fs-extra");
const today = new Date();
const date = today.getFullYear() + "-" + (today.getMonth() + 1) + "-" + today.getDate();
const storage = multer.diskStorage({
destination: (req, file, callback) => {
const { companyID, flowID } = req.body;
let path = `./uploads/${companyID}/${flowID}`;
fs.mkdirsSync(path);
callback(null, path);
},
filename: (req, file, cb) => {
crypto.pseudoRandomBytes(8, (err, raw) => {
if (err) return cb(err);
cb(
null,
date + "_" + raw.toString("hex") + "_" + path.extname(file.originalname)
);
});
}
});
//Must be under storage
const upload = multer({ storage: storage }).single("upload");
const deleteFileFromServer = (companyID, flowID, filePath) => {
return new Promise((resolve,reject)=>{
fs.unlink(`./uploads/${companyID}/${flowID}/${filePath}`).then(()=>{
resolve("File Deleted");
}).catch((err)=> {
reject(err);
})
})
};
module.exports = {
upload: upload,
deleteFileFromServer: deleteFileFromServer
};
my route: Here i want handle destination in every route set diffrent destination
router.post("/uploadfile", upload, (req, res, next) => {
const file = req.file;
const flowID = req.body.flowID;
if (!file) {
const error = new Error("Please upload a file");
error.httpStatusCode = 400;
return next(error);
} else {
createFileInDB(file.originalname, flowID, file.filename)
.then(() => {
console.log("File Created");
res.json(file);
})
.catch(err => {
res.status(500).send(err);
});
}
});
What i want it to be? i want that every route i can choose different destination.
router.post("/uploadfile", upload, (req, res, next) => {
upload.destination = "my path/"
});
Thanks!!

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