Why doesn't work the multer as a middleware? - node.js

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

Related

'Cannot GET /api/items'

Working on a MERN application as a way to learn how it all works, but I am stuck trying to get my routes to display. I don't get any other errors, and if I use a simple app.get('/'), I am able to see that just fine; it seems that the routes I have defined are not being recognized for some reason.
require('dotenv').config();
const express = require('express');
const cors = require('cors');
const app = express();
const port = process.env.PORT;
const options = {
origin: 'http://localhost:8081'
}
app.use(cors(options));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
const db = require('./models');
db.mongoose
.connect(db.url, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => {
console.log('Successfully connected.');
})
.catch((error) =>{
console.log(`Connection failed. Error: ${error}`);
process.exit();
}
);
require('./routes/items.routes')(app)
app.listen(port, () => {
console.log(`Listening at localhost:${port}`);
});
const multer = require('multer');
const dir = './public/';
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, dir);
},
filename: (req, file, cb) => {
const fileName = file.originalname.toLowerCase().split(' ').join('-');
cb(null, fileName + '-' + Date.now());
}
});
var upload = multer({
storage: storage,
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('Invalid file type.'));
}
}
});
module.exports = app => {
const items = require('../controllers/items.controller');
let router = require('express').Router();
router.post('/', upload.single('icon'), items.create);
router.delete('/:id', items.delete);
app.use('/api/items', router);
};
I followed this and this as a start point. Unsure what I am missing or why it is unable to retrieve my POST route.
The error in your title:
Cannot GET /api/items
means it is a GET request to /api/items. But, you don't have a GET handler for that route. You only have a POST handler for that route defined with these two lines of code:
router.post('/', upload.single('icon'), items.create);
app.use('/api/items', router);
So, you apparently need to change your test on that route to a POST, not a GET and the POST will be expecting a body part with the data for an icon in it.
If you want to see exactly what is getting to your router (for debugging/troubleshooting purposes), you can add this right after you declare the router as the first item you register on the router.
router.use((req, res, next) => {
console.log(`In router: ${req.method}:${req.originalUrl}`);
next();
});

upload images with nodejs

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/

Express server not responding route request

My express server is not responding to any of the route requests, whatever I do no luck.
following are the routes I am trying to access:
http://localhost:3000/api/files
http://localhost:3000/files/<:uuid>
http://localhost:3000/api/files/send
Terminal output:
Response via insomia:
Following are the files of the project
server.js
const express = require('express');
const app = express();
const path = require('path');
app.use(express.static('public'));
app.use(express.json);
const PORT = process.env.PORT||3000;
const connectDB = require('./config/db');
connectDB();
app.set('views', path.join(__dirname, '/views'));
app.set('view engine', 'ejs');
app.use('/api/files', require('./routes/files'));
app.use('/files', require('./routes/show'));
app.use('/files/download', require('./routes/download'));
console.log("Server");
app.listen(PORT, () =>{
console.log(`Listening on port ${PORT}`);
});
routes/files.js
const router = require('express').Router();
const multer = require('multer');
const path = require('path');
const File = require('../models/file');
const {v4 : uuid4} = require('uuid');
const sendMail = require('../services/email');
require('dotenv').config();
let storage = multer.diskStorage({
destination: (req, file, cb) => cb(null, 'uploads/'),
filename: (req, file, cb) => {
const uniqueName = `${Date.now()}-${Math.round(Math.random() * 1E9)}${path.extname(file.originalname)}`;
cb(null, uniqueName)
},
});
let upload = multer({
storage:storage,
limit: { fileSize: 100000*200},
}).single('myfile');
router.post('/', (req, res) => {
console.log("Reached here");
console.log(req);
// store locally
upload(req, res, async (err) => {
// check for valid req
if(!req.file){
return res.json({
error: "Error processing file!"
});
}
if(err){ return res.status(500).send({error: err.message})}
// store in db
const file = File({
filename: req.file.filename,
uuid: uuid4(),
path: req.file.path,
size: req.file.size,
});
const response = await file.save();
return res.json({file: `${process.env['APP_BASE_URL']}/files/${response.uuid}`})
});
//return link
});
router.post('/send', async (req, res) => {
console.log(req.body);
const {uuid, emailTo, emailFrom} = req.body;
if(!uuid || !emailTo || !emailFrom){ return res.status(422).send({error: 'All files are required.'});}
const file = await File.findOne({uuid: uuid});
if(file.sender){
return res.status(422).send({error: 'Email already sent.'});
}
file.sender = emailFrom;
file.receiver = emailTo;
const response = await file.save();
sendMail({
from: emailFrom,
to: emailTo,
subject: "shareMe File Sharing",
text: `${emailFrom} shared a file with you`,
html: require('../service/template')({
emailFrom: emailFrom,
downloadLink: `${process.env['APP_BASE_URL']}/files/${file.uuid}`,
size: parseInt(file.size/1000)+'KB',
expires: '24 hours'
})
});
return res.send({success: true});
});
module.exports=router;
routes/show.js
const router = require('express').Router();
const File = require('../models/file');
router.get('/:uuid', async (req, res) => {
try{
const file = await File.findOne({
uuid: req.params.uuid
});
if(!file){
return res.render('download', {error: 'File not fetched.'});
}
console.log(`${process.env['APP_BASE_URL']}/files/download/${file.uuid}`);
return res.render('download', {
uuid: file.uuid,
fileName: file.filename,
size: file.size,
downloadLink: `${process.env['APP_BASE_URL']}/files/download/${file.uuid}`,
});
}catch(err){
return res.render('download', {error: 'Something seems to be upset :('});
}
});
module.exports = router;
routes/download.js
const router = require('express').Router();
const File = require('../models/file');
router.get('/:uuid', async (req, res) => {
// Extract link and get file from storage send download stream
const file = await File.findOne({ uuid: req.params.uuid });
// Link expired
if(!file) {
return res.render('download', { error: 'Link has been expired.'});
}
const response = await file.save();
const filePath = `${__dirname}/../${file.path}`;
res.download(filePath);
});
module.exports = router;

Error: Command failed: Invalid Parameter - -resize

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;

Node.js - expressjs - multer req.files outputs empty

i'm using multer to get a file from this form
<form action="/api/pimage" method="POST" enctype="multipart/form-data">
<fieldset>
<input type="file" name="profileimage">
<input type="submit">
</fieldset>
</form>
using this serverside script
app.post('/api/pimage', function(req, res, next) {
console.log(req.body, req.files);
});
the problem is that req.body is printing out { profileimage: 'image.png' }
and req.files is printing out {}
where you see the problem?
thanks
P.S. i'm using app.use(bodyParser.urlencoded({ extended: false })); to get req.body and app.use(multer({ dest: './uploads/'})); for req.files
I found that using multer alongside bodyParser can cause req.file to be undefined. Make sure to check that also if you're having issues.
I put MY (there are many I imagine and surely better) solution to help many people like me because I have searched during 1 entire day ;-(
var express = require('express');
var fileUpload = require('express-fileupload');
var fs = require("fs");
var app = express();
console.log('étape 0');
app.use(express.static('mesStatic'));
app.use(fileUpload());
console.log('étape 1');
app.get('/indexFileUpload.htm', function (req, res) {
res.sendFile( __dirname + "/" + "indexFileUpload.htm" );
})
console.log('étape 2');
app.post('/file_upload', function (req, res) {
console.log('étape 3');
console.log('req.files:' , req.files);
if (!req.files) {
res.send('No files to upload.');
return;
}
console.log('req.files.file.data:' , req.files.file.data);
var bufDataFile = new Buffer(req.files.file.data, "utf-8");
console.log('étape 3.1');
console.log('__dirname : ' + __dirname);
fs.writeFile(__dirname + '/file_upload/output.txt', bufDataFile, function(err) {
if (err) {
return console.error(err);
}
else {
console.log("Data written successfully !");
}
console.log('étape 4');
res.end('Fin OK !!!');
})
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port);
})
You have to provide your upload function defined for multer before asking for req.file in function(req, res), you can follow the code given below
var Storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, "./images/");
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '_' + Date.now() + '.jpg');
}
});
var upload = multer({ storage: Storage }).single('imagePath');
router.post('/file_upload', upload, function(req, res, next){
console.log(req.file);
var Storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, "./public/images/");
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '_' + Date.now() + '.jpg');
}
});
var upload = multer({ storage: Storage }).single('imagePath');
router.post('/add-product', upload, function(req, res, next){
var newProduct = new Product();
}

Resources