const express = require('express');
const multer = require('multer');
var fs = require('fs')
, gm = require('gm').subClass({imageMagick: true});
const router = express.Router();
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, './public/images')
},
filename: (req, file, cb) => {
cb(null, file.originalname + '-' + Date.now() + '.png')
}
})
var upload = multer({ storage: storage }).single('image');
router.get('/', (req, res, next) => {
res.render('index', {
title: 'Express'
})
});
router.post('/', upload, (req, res, next) => {
gm(req.file.path)
.resize(240, 240)
.gravity('Center')
.extent(240, 240)
.noProfile()
.write('./public/images/update/' + req.file.originalname + '-' + Date.now(), function(err){
console.log('err', err);
})
})
module.exports = router;
Related
I the app.js there is a direct route app.post('/upload', upload.single('image'), (req, res) => { res.json({ message: 'pic uploaded' }); });
When I make a post request to /upload, the image will be uploaded. However, when I use it like app.use('/phones', phoneRoutes); then the image won't be uploaded. Can you tell me where is the mistake? In both files everything is the same, but as I said, it works only in the app.js.
app.js:
require('dotenv').config();
const express = require('express');
const mongoose = require('mongoose');
const phoneRoutes = require('./routes/phoneRoute');
const multer = require('multer');
const cors = require('cors');
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, './images');
},
filename: (req, file, cb) => {
console.log('file: ', file);
cb(null, Date.now() + file.originalname);
},
});
const upload = multer({ storage: storage });
//initialize
const app = express();
//middleware
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
//routes
app.post('/upload', upload.single('image'), (req, res) => {
res.json({ message: 'pic uploaded' });
});
app.use('/phones', phoneRoutes);
//connect to mongodb
mongoose
.connect(process.env.MONGO_URI)
.then(() => {
app.listen(process.env.PORT);
console.log('Connected to mongodb: ', process.env.PORT);
})
.catch((err) => console.log(err));
phoneRoutes.js:
const router = require('express').Router();
const { createPhone } = require('../controllers/phoneController');
const multer = require('multer');
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, '../images');
},
filename: (req, file, cb) => {
console.log('file: ', file);
cb(null, Date.now() + file.originalname);
},
});
const upload = multer({ storage: storage });
router.get('/:id', (req, res) => {
res.json({ message: 'get phone: ' + req.params.id });
});
router.get('/', (req, res) => {
res.json({ message: ' all Phones' });
});
router.delete('/:id', (req, res) => {
res.json({ message: 'phone ' + req.params.id + ' is deleted' });
});
router.post('/', upload.single('image'), (req, res) => {
res.json({ message: 'pic is uploaded' });
});
module.exports = router;
Your statement
cb(null, '../images');
contains a relative path, which is probably evaluated relative to the current working directory of the Node.js process. It is safer to make it relative to the directory containing the Javascript file phoneRoutes.js:
cb(null, __dirname + '/../images');
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/
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
});
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!.");
}
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.