upload images with nodejs - node.js

i have a user.js in model folder
const UserSchema = new mongoose.Schema({
name: {
type: String,
},
profile_pic: {
data: Buffer,
contentType: String
}
})
i want to upload a profile picture
and in the router folder i defined the storage using multer
const storage = multer.diskStorage({
destination: (req, file, callback) => {
callback(null, './images')
},
filename: (req, file, callback) => {
callback(null , Date.now()+ file.originalname)
}
})
const upload = multer({
storage : storage,
limits : {
fieldSize : 1024*1024*3
}
})
router.post('/image' , upload.single('image'),image)
using postman i tried to upload an image .. it uploaded successfully and stored in the defined folder (images)
but i want to store the image in the model too
how to store it in the controller folder user.js

Try the example below
const app = require("express")();
const multer = require('multer')
const firstLocation = multer.diskStorage({
destination: function (req, file, cb) {');
cb(null, './imagesFolder/')
},
filename: (req, file, callback) => {
callback(null , Date.now()+ file.originalname)
}
});
const secondLocation = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './modelFolder/')
},
filename: (req, file, callback) => {
callback(null , Date.now()+ file.originalname)
}
});
const firstPath = multer({ storage: firstLocation })
const secondPath = multer({ storage: secondLocation })
function fileUpload(req, res, next) {
firstPath.single('file')(req, res, next);
secondPath.single('file')(req, res, next);
next();
}
app.post("/", fileUpload, (req, res) => {
res.send("Received file");
});
app.listen(3000, () => {
console.log("Server started");
});
If you run the above code and send a request to localhost:3000 then you will notice that two directories created named imagesFolder and modelFolder. Inside those folders, you will see the file that you have uploaded.
Updated answer in response to comments for Mongo schema,
const imagePath = '/path/to/myImage.jpg';
const imageUp = mongoose.model('imageUp', UserSchema);
mongoose.connection.on('open', function () {
imageUp.remove((err) => {
if (err) throw err;
const up = new imageUp;
up.img.data = fs.readFileSync(imagePath); // read from you folder
up.img.contentType = 'image/jpg'; // set the content tpe to image format
up.save((err, a) => { // save or upload image
if (err) throw err; // throws error if anything goes wrong
app.get('/', (req, res, next) => {
imageUp.findById(up, (err, doc) => { // fetch image from db by id and send in response as required.
if (err) return next(err);
res.contentType(doc.img.contentType);
res.send(doc.img.data);
});
});
}
Ref:- https://www.geeksforgeeks.org/upload-and-retrieve-image-on-mongodb-using-mongoose/

Related

Multer fileFilter is not getting called and req.body is empty

for some reason the fileFilter on multer is not getting called.
here is my Controller (i am using express routers)
const express = require('express');
const router = express.Router();
const UploadController = require('../controllers/UploadController');
router.route('/upload').post(UploadController.upload);
module.exports = router;
and this is the controller
const multer = require('multer');
const fs = require('fs');
module.exports = {
upload: function (req, res) {
let storage = multer.diskStorage({
destination: function (req, file, cb) {
console.log('here');
const filesDir = './uploads/' + req.body.ref;
if (!fs.existsSync(filesDir)) {
fs.mkdirSync(filesDir);
}
cb(null, filesDir);
},
filename: function (req, file, cb) {
let extArray = file.mimetype.split("/");
let extension = extArray[extArray.length - 1];
cb(null, req.body.type + '-' + Date.now() + '.' + extension);
},
fileFilter : function (req, file, cb) {
if (!file.originalname.match(/\.(jpg|jpeg|png|gif)$/)) {
return cb(new Error('Only image files are allowed!'), false);
}
cb(null, true);
}
})
const upload = multer({ storage: storage }).single('file');
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
res.send({
error: err
});
} else if (err) {
res.send({
error: err
});
}else{
res.send({
file: req.file,
body: req.body
});
}
});
}
}
I have following issues:
The fileFilter function is not even called so its not validating files
the req.body on the upload function (upload: function (req, res)) is empty it is only available in diskStorage and last upload function (upload(req, res, function (err)) so i cannot validate the body data also.
I had the same problem. the fileFilter function has to be defined inside multer, not inside the diskStorage function.
To make it a bit more readable I defined the storage and filter in variables instead of making everything inside the multer call.
// storage settings
const multerStorage = multer.diskStorage({
destination: function(req, file, next) {
next(null, './public/files');
},
filename: function(req, file, next) {
const sanitizedName = file.originalname
.replace('/[^a-z0-9\./gi', '-')
.replace('/-{2,}/g', '-')
.toLowerCase();
const name = Date.now() + '-' + sanitizedName;
// sending the file name to be stored in the database
req.body.filename = name;
next(null, name);
},
limits: {
fileSize: 25000000
}
});
// filter function
const multerFilter = function(req, file, cb) {
const ext = path.extname(file.originalname).toLowerCase();
if (ext !== '.pdf') {
cb(new Error('File must be in PDF format.'));
}
cb(null, true);
}
And then applying the storage settings and filter function to multer:
const upload = multer({
storage: multerStorage,
fileFilter: multerFilter
});

Same Image not uploading in express

I am trying to upload an image using express but I am facing two problems, first, whenever I upload the same image again it's not getting uploaded and secondly after uploading any single image a file with image also uploading. Here is my code.
var multer = require('multer');
var uploads = multer({dest: './images'});
app.post('/uploading', uploads.single("file"), function (req, res) {
var file = __dirname +"/images" + "/" + req.file.originalname;
fs.readFile( req.file.path, function (err, data) {
fs.writeFile(file, data, function (err,data) {
if( err ){
console.error( err );
response = {
message: 'Sorry, file couldn\'t be uploaded.',
filename: req.file.originalname
};
}else{
response = {
message: 'File uploaded successfully',
filename: req.file.originalname
};
}
res.end( JSON.stringify( response ) );
});
});
})
The uploads.single("file") middleware Will handle the file upload. You don't have to specifically fs.read and fs.write the file.
var multer = require('multer');
var uploads = multer({dest: './images'});
app.post('/uploading', uploads.single("file"), function (req, res) {
//the file is uploaded automatically
})
EDIT: The above code will upload the file with hex string as filename without any extension.
In order to add rename function you need to use diskStorage. Here is the code taken from this github issue page.
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './images/')
},
filename: function (req, file, cb) {
crypto.pseudoRandomBytes(16, function (err, raw) {
cb(null, raw.toString('hex') + Date.now() + '.' + mime.extension(file.mimetype)); //this is the rename func
});
}
});
var uploads = multer({ storage: storage });
app.post('/uploading', uploads.single("file"), function (req, res) {
//the file is uploaded automatically
})
Now you can use the uploads variable as middleware as shown in the above snippet.
you can edit the filename: function (req, file, cb) { .. } according to your needs. Now the filename will be, <16characterhexstring>.ext
another way to handle it will be not using middleware and using multer manually with below options :
try {
var storage = multer.diskStorage({
destination: function(request, file, callback) {
//define folder here by fs.mkdirSync(anyDirName);
},
filename: function(req, file, callback) {
callback(null, anyFileName);
},
limits: self.limits
});
var upload = multer({
storage: storage,
fileFilter: function(request, file, callback) {
// here you can filter out what not to upload..
}
}).any();
upload(request, response, callback);
} catch (e) {
}
hope this helps!

Multer callback when file is uploaded in the disk completely

I have written the code for multer as shown below:
const storage = multer.diskStorage({
destination(req, file, callback) {
callback(null, './public/images')
},
filename(req, file, callback) {
profile_image = `${file.fieldname}-${Date.now()}${path.extname(file.originalname)}`;
callback(null, profile_image)
}
});
const xyz = (req, res) => {
upload = multer({
limits: {
fileSize: 1000000,
files: 2
},
storage,
fileFilter(req, file, callback) {
const ext = path.extname(file.originalname);
if (ext !== '.png' && ext !== '.jpg' && ext !== '.gif' && ext !== '.jpeg') {
return callback(res.end('Only images are allowed'), null)
}
callback(null, true);
}
}).any();
upload(req, res, err => {
})
upload starts working the moment there is no error in uploading file, but not when the file is uploaded successfully in the disk. So is there any other callback through which I can know when the file is successfully uploaded in the disk?
Try this it might solves your issue. You can check success in upload function in below example.
var Express = require('express');
var multer = require('multer');
var bodyParser = require('body-parser');
var app = Express();
app.use(bodyParser.json());
var Storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, "./Images");
},
filename: function (req, file, callback) {
callback(null, file.fieldname + "_" + Date.now() + "_" + file.originalname);
}
});
var upload = multer({ storage: Storage }).array("imgUploader", 3); //Field name and max count
app.get("/", function (req, res) {
res.sendFile(__dirname + "/index.html");
});
app.post("/api/Upload", function (req, res) {
upload(req, res, function (err) {
if (err) {
return res.end("Something went wrong!");
}
return res.end("File uploaded sucessfully!.");
});
});
app.listen(2000, function (a) {
console.log("Listening to port 2000");
});
Check in your upload function like this
upload(req, res, err => {
if (err) {
res.end("Something went wrong!");
}
res.end("File uploaded sucessfully!.");
}

nodejs how to upload image from API

I am new to node JS and i have made function for uploading image from API.
But when i hit the URL from postman using form-data having field name image then in response it shows me.
Here is the postman image
Error uploading file
below is my code
My router.js contain:-
var express = require('express');
var router = express.Router();
var ctrlSteuern = require('../controllers/steuern.controllers.js');
router
.route('/steuern/image_upload')
.post(ctrlSteuern.imageUpload);
in Controller i have:-
var multer = require('multer');
var multiparty = require('multiparty');
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './image');
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '-' + Date.now());
}
});
var upload = multer({ storage : storage}).single('image');
module.exports.imageUpload = function(req, res){
upload(req,res,function(err) {
if(err) {
return res.end("Error uploading file.");
}
return res.end("File is uploaded");
});
}
Here is my code for saving image to folder.
exports.saveMedia = (req, res) => {
const storage = multer.diskStorage({
destination: (req, file, callback) => {
callback(null, (config.const.path.base + config.const.path.productReviewMedia));
},
filename: (req, file, callback) => {
callback(null, Date.now() + '-' + file.originalname);
}
});
const upload = multer({storage: storage}).any('file');
upload(req, res, (err) => {
if (err) {
return res.status(400).send({
message: helper.getErrorMessage(err)
});
}
let results = req.files.map((file) => {
return {
mediaName: file.filename,
origMediaName: file.originalname,
mediaSource: 'http://' + req.headers.host + config.const.path.productReviewMedia + file.filename
}
});
res.status(200).json(results);
});
}
Here is post man request.

Express - multer fileFilter error handling

I'm tryng to upload a file and the upload goes ok! The problem is when I try to upload some file that is not accepted according to me fileFitler handling. I would like to receive some error in console or redirect the user to the back page, but I'm just receiving a error on brower : cannot read read property filename of undefined.
But, if I upload some extension that is accepted, goes ok!
Here is my code:
const mongoose = require('mongoose');
const multer = require('multer');
const uuidV4 = require('uuid/v4');
const Video = require('../models/videoModel');
function fileFilter(req, file, cb){
const extension = file.mimetype.split('/')[0];
if(extension !== 'video'){
return cb(null, false), new Error('Something went wrong');
}
cb(null, true);
};
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads')
},
filename: function (req, file, cb) {
const newName = uuidV4();
const extension = file.mimetype.split('/')[1];
cb(null, newName +`.${extension}`);
}
});
var upload = multer({ storage: storage, fileFilter: fileFilter});
exports.uploadVideo = upload.single('file'); // the single param should be the name of the file input form
exports.CreateVideo = (req, res) => {
const newVideo = {title: req.body.title, path: req.file.filename};
Video.create(newVideo, function(err, result){
if(err){
console.log('Não foi possível realizar o upload do vídeo.' + err);
}
else{
console.log('Vídeo upado com sucesso!');
res.redirect('/');
console.log(result);
}
})
};
exports.Home = (req, res) =>{
res.render('index');
};
exports.ShowVideos = (req, res) =>{
Video.find({}, function(err, result){
if(err){
res.redirect('/');
}
else{
res.render('video', {videoData:result});
}
})
};
The get an error on the console, you could change your fileFilter and pass an error to the cb function. See:
function fileFilter(req, file, cb){
const extension = file.mimetype.split('/')[0];
if(extension !== 'video'){
return cb(new Error('Something went wrong'), false);
}
cb(null, true);
};
Hope it helps!!

Resources