I am creating an app using Node, Express and Handlebars and multer for uploading images. Every time I submit the form, req.file is undefined. I've spent the entire day troubleshooting but can't figure out what I'm doing wrong.
Router File:
const express = require('express');
const router = express.Router();
const multer = require('multer');
const mongoose = require('mongoose');
const path = require('path');
const methodOverride = require('method-override');
//Set Storage Engine
const storage = multer.diskStorage({
destination: './public/uploads/images',
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now() +
path.extname(file.originalname));
}
});
const upload = multer({
storage: storage
}).single('featuredImage');
//Change Featured Image - POST
router.post('/saveImage/:id', (req, res) => {
console.log(req.file);
//removed the rest of the code to keep it simple. req.file here is always undefined.
});
Form
<form action="/saveImage/{{pitch.id}}" method="POST" enctype="multipart/form-data">
<div class="form-group">
<label for="featuredImage">Featured Image</label>
<input type="file" name="featuredImage" id="featuredImage">
</div>
<input type="submit" value="SAVE">
</form>
app.js these requires are in the app.js file.
const express = require('express');
const exphbs = require('express-handlebars');
const path = require('path');
const passport = require('passport');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const flash = require('connect-flash');
const session = require('express-session');
const methodOverride = require('method-override');
const nodemailer = require('nodemailer');
//Set StaticFolder
app.use(express.static(path.join(__dirname, 'public')));
You need to add upload.single('featuredImage') as middleware for the respective route as follows.
const upload = multer({storage: storage});
//Change Featured Image - POST
router.post('/saveImage/:id',upload.single('featuredImage'), (req, res) => {
console.log(req.file);
//removed the rest of the code to keep it simple. req.file here is always undefined.
});
In my case it was issue with image size. I resolved it with defining multer limit as follows:
const upload = multer({ storage: storage, limits: { fieldSize: 10 * 1024 * 1024 } }); //10MB
Took me ages to figured out.
Maybe this can help someone
Please refer to this question. It has answer you are looking for.
node js multer file upload not working. req.file and req.files always undefined
You have to pass middleware
router.post('/saveImage/:id', upload.single('featuredImage'), (req, res) => {
console.log(req.file);
});
At first I was having the same issue! But when I added this :
const { storage } = require ('debug/src/browser');
... it worked.
This is my multer code :
const { storage } = require('debug/src/browser');
const multer = require('multer');
const MINE_TYPES = {
'image/jpg' : 'jpg',
'image/jpeg': 'jpeg',
'image/png':'png'
}
const Storage = multer.diskstorage({
destination: (req, file, callback)=>{
callback(null, "public/images/articles")
},
filename: (req, file, callback) => {
var name = Math.floor(Math.random() * Math.floor(15258652325)).tostring()
name = Math.floor(Math.random() * Math.floor(15258652325)).toString();
name = Math.floor (Math.random() * Math.floor(15258652325)).toString();
name = Math.floor(Math.random() * Math.floor(15258652325)).tostring();
name = Math.floor(Math.random() * Math.floor
(15258652325)).toString();
name += Date.now();
const extension = MINE_TYPES[file.mimetype];
name += extension;
callback(null,name);
module.exports = multer({ storage: Storage)).
single('image');
I was facing the same issue and you can solve it by following these steps:
1- First add these line in your server.js or index.js root file
app.use(express.json());
app.use(express.urlencoded({
extended: true,
})
);
2- Create a folder name middleware and inside it create a file name upload.js or any name that you want.
3- Place the following code in upload.js file
const multer = require("multer");
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "public/");
},
filename: function (req, file, cb) {
const imgName = file.originalname;
cb(null, imgName );
},
});
const upload = multer({
storage: storage,
});
module.exports = upload;
4- Now you can use this middleware in any route. For example:
const upload = require("../middlewares/fileUpload");
router.route("/send").post(upload.single("profile"),
((req,res) => {
*your controller logic here*
});
**Note: Here profile is the name of the file key that you are sending**
Use this:
var fileupload = require("express-fileupload");
app.use(fileupload());
Related
I want to upload an image in a vuejs storage with an API built with NodeJS and Express.
So I found a tutorial
First, I ran the command
npm install express-fileupload
and I added
const fileUpload = require('express-fileupload');
app.use(fileUpload());
my code for API (nodeJS & Express) :
const port = 000; // for security!
const express = require('express');
var app = express();
const mysql = require("mysql");;
const path = require('path');
const nodemailer = require('nodemailer');
var cors = require('cors');
app.use(cors());
const res = require('express/lib/response');
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
const { PrismaClient, Type } = require('#prisma/client');
const prisma = new PrismaClient();
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const htmlspecialchars = require("htmlspecialchars");
const striptags = require("striptags");
const { accessSync } = require('fs');
const fileUpload = require('express-fileupload');
app.use(fileUpload());
app.post('/upload', (req, res) => {
console.log('jentre dans mon upload') ;
// Get the file that was set to our field named "image"
var { image } = req.files;
console.log(req.files);
// If no image submitted, exit
//if (!image) return res.sendStatus(400);
// If does not have image mime type prevent from uploading
//if (/^image/.test(image.mimetype)) return res.sendStatus(400);
// Move the uploaded image to our upload folder
//console.log(__dirname + '/src/components/upload/' + image.name);
//image.mv(__dirname + '/src/components/upload/' + image.name);
// All good
res.sendStatus(200);
});
my folders :
In my front a make a form :
<form action="http://localhost:195/upload" method="POST" enctype="form-data">
<input type="file" name="image" />
<button type="submit">Upload</button>
</form>
my page :
So, when i want to upload an image i have this error :
"jentre dans mon upload
TypeError: Cannot destructure property 'image' of 'req.files' as it is undefined."
(the same error appeared in my terminal for the api)
I don't understand this error, why req.files is not defined...
Thank you for your help and have a good day !
multer is causing uncaught error though if i do req.file i am able log image without any issue however when i do req.file.filename i am getting uncaught error, in the form name image is correctly declared and i can see image on terminal on post request through req.file once again. thanks
const router = express.Router();
const bodyParser = require("body-parser")
const multer = require("multer");
const path = require("path");
const fs = require("fs");
const upload = multer({ dest: "uploads/" });
app.use(bodyParser.urlencoded({ extended: false }));
router.post("/", upload.single("image"), async (req, res, next) => {
var fileName = req.file.filename;
console.log(fileName);
})
I've tried multer before in the past and it worked perfectly, but this time I can't get the image to load even when my path is correct and the file exists.
Here's my app.js on Node
require('dotenv').config();
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
const path = require('path')
app.use(express.urlencoded({ extended: true}));
app.use(express.json());
app.use('/tmp/my-uploads',express.static(path.join(__dirname,'/tmp/my-uploads')))
const routes = require('./routes');
app.use(routes);
app.listen(PORT, () => {
console.log('Listening on port : ', PORT);
})
Multer Middleware
const multer = require("multer");
const path = require("path");
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "./tmp/my-uploads");
},
filename: function (req, file, cb) {
const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9);
cb(
null,
file.fieldname + "-" + uniqueSuffix + path.extname(file.originalname)
);
},
});
const upload = multer({ storage: storage });
module.exports = upload;
From my react front end to show the image
const image = CarsImages.filter((image) => {
if(image.primary === true){
return `http://localhost:3000/tmp/my-uploads/${image.filename}`;
}
})
Proof that the image exist, but doesnt load
screenshot
My local storage location
screenshot
Feel free to ask me further questions if you need more details
I have question.I've looked at some questions here, but I can't get the answer.My question is, I want to upload and read a json file, I try with "multer" but couldn't.So I want to put the file I upload to the result variable. Can you help me? How can I achieve this?
HTML;
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
<form action="/import" enctype="multipart/form-data" method="post">
<input type="file" name="filename">
<input type="submit" value="Upload">
</form>
</body>
</html>
Server.js
const express = require('express');
const multer = require('multer');
const upload = multer({
dest: 'uploads/' // "uploads"
});
const app = express();
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
route.post("/import", upload.single("filename") (req, res, next) => {
var result = require(# I want to send the json file I uploaded here, and I need to see the contents of the json file as is #)
res.json(result)
res.redirect("/")
});
app.listen(3000);
The upload.single() parses the data stream and saves as a file based on the configuration. In your case, it will look for filename field in the incoming request and save the file in the uploads/ folder. The metadata of the file is available in req.file object. You can simply do console.log(req.file) to see the information.
To read the content of the file, you can use req.file.path field. Here is how:
const fs = require("fs");
const path = require("path");
/** In the controller */
const absolutePath = path.join(__dirname, req.file.path);
const jsonString = fs.readFileSync(absolutePath, "utf-8");
const jsonObject = JSON.parse(jsonString);
console.log(jsonObject);
Here is how the complete server.js would look like:
const express = require("express");
const multer = require("multer");
const fs = require("fs");
const path = require("path");
const upload = multer({
dest: "uploads/" // "uploads"
});
const app = express();
app.get("/", (req, res) => {
res.sendFile(__dirname + "/index.html");
});
const route = express.Router();
route.post("/import", upload.single("filename"), (req, res, next) => {
console.log(req.file);
const absolutePath = path.join(__dirname, req.file.path);
const jsonString = fs.readFileSync(absolutePath, "utf-8");
const jsonObject = JSON.parse(jsonString);
console.log(jsonObject);
res.redirect("/");
});
app.use(route);
app.listen(3000);
I have added some parts which were missing from your snippet ( like express.Router ). They might be different though.
I am using :
"ejs": "^2.5.6",
"express": "^4.14.0",
"express-validator": "^3.2.0",
"multer": "^1.3.0",
My form is :
<form id="offer-form" role="form" enctype="multipart/form-data" action="/subfolder/86" method="POST">
<input type="text" name="name"/>
<input type="file" name="images"/>
<input type="file" name="images"/>
<button type="submit">Submit</submit>
</form>
My server route:
var path = require('path');
var express = require('express');
var bodyParser = require('body-parser');
var expressValidator = require('express-validator');
var osmodule = require('../../osmodule');
var Multer = require('multer');
var request = require('request');
const multer = Multer({
storage: Multer.memoryStorage(),
limits: {
fileSize: 5 * 1024 * 1024 // no larger than 5mb, you can change as needed.
}
});
//Adding a new subfolder
app.post('/subfolder/:id', multer.array({ name: 'images', maxCount: 6 }), expressValidator, function (req, res, next) {
console.log("Form Submitted");
}).use(function (req, res, next) {
res.setHeader('Content-Type', 'text/plain');
res.status(404).send('Not Found ! ');
});
Normally this code should print on the console the message
Form submitted
but the server is receiving nothing not even
Not Found
I have just noticed the problem is with using multer and expressValidator. If I remove expressValidator, it is working but if I add it, it is not working. I need expressValidator to validate user data. Is there any other validator which will accept to be used with multer?
I think this might be due to the validator not being initialize properly.
Try the following by adding the following two lines before the app.post.
INIT
app.use(bodyParser.json()); //To enable post request over node api.
app.use(expressValidator([options])); // this line must be immediately after any of the bodyParser middlewares!
Then you configure your validation inside the app.post
req.checkBody('postparam', 'Invalid postparam').notEmpty().isInt();
See all the available options
Remember to remove expressValidator from the current app.post method above
I found the solution of using both of these middlewares, I just called the before the action and called the express-validator after calling multer:
var path = require('path');
var express = require('express');
var bodyParser = require('body-parser');
var expressValidator = require('express-validator');
var osmodule = require('../../osmodule');
var Multer = require('multer');
var request = require('request');
const multer = Multer({
storage: Multer.memoryStorage(),
limits: {
fileSize: 5 * 1024 * 1024 // no larger than 5mb, you can change as needed.
}
});
app.get('/home',function(req,res){
console.log("Welcome Brother");
})
.use(multer.array({ name: 'images', maxCount: 6 });
.use(expressValidator);
.post('/subfolder/:id', function (req, res, next) {
console.log("Form Submitted");
}).use(function (req, res, next) {
res.setHeader('Content-Type', 'text/plain');
res.status(404).send('Not Found ! ');
});