I am not able to upload two images from two different input tags using Multer.
This is the code of the html form
<form action="/upload" method="post" enctype="multipart/form-data">
<h1>Upload Image 1</h1>
<input name="photo1" type="file" />
<img id="output_image" />
<h1>Upload Image 2</h1>
<input name="photo2" type="file" />
<img id="output_image1" />
<button type="submit">Upload</button>
</form>
This is the code of the nodejs file
const upload = multer({ dest: 'uploads/' })
app.post('/upload', upload.fields([
{ name: 'photo1', maxCount: 1},
{ name: 'photo2', maxCount: 1}
]), (req, res, next) => {
console.log(req.file);
next();
});
But the request object is always undefined.
I tried following the documentation but it didn't solve this issue.
Previously I tried uploading a single file which did work out. For that I removed the below part of the form
<h1>Upload Image 2</h1>
<input name="photo2" type="file" />
<img id="output_image1" />
And this was the nodejs file same as the one on the documentation
const upload = multer({ dest: 'uploads/' })
app.post('/upload', upload.single('photo1'), (req, res, next) => {
console.log(req.file);
next();
});
I am not able to find the mistake here. Is it not possible to take two images from different input fields using multer? Any suggestions would be appreciated.
Use any of the following approaches
Will this help you .any()
Accepts all files that comes over the wire. An array of files will be stored in req.files.
WARNING: Make sure that you always handle the files that a user uploads. Never add multer as a global middleware since a malicious user could upload files to a route that you didn't anticipate. Only use this function on routes where you are handling the uploaded files.
i am saying this from [here][1].
or for multiple files use this
Instead of upload.single('image') you want to do upload.array('image'), and then look at req.files instead of req.file.
3)
app.post("/upload", function(req, res, fields) {
const storage = multer.diskStorage({
destination: "public/data/",
filename: function(req, file, cb){
crypto.randomBytes(20, (err, buf) => {
cb(null, buf.toString("hex") + path.extname(file.originalname))
})
}
});
const upload = multer({
storage: storage
}).fields([{name: "pp"}, {name: "banner"}]);
upload(req, res, (err) => {
if (err) throw err;
});
});
for more explanation https://codingstatus.com/upload-multiple-files-using-multer-in-node-js-and-express/
Related
Preface: using Node.js w/Express to build a blog website and using multer to upload an image to mongoDB.
I have a problem with image data not saving to MongoDB.
When I use enctype="multipart/form-data in my HTML form, I get the following in my terminal
fieldname: 'myImage',
originalname: 'photo_2021-12-27_20-07-58.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: './uploads/',
filename: 'photo_2021-12-27_20-07-58.jpg',
path: 'uploads\\photo_2021-12-27_20-07-58.jpg',
size: 134172
}
Which is correct, the image also uploads into a separate uploads folder which is also correct, however the image data doesn't save to my mongoDB.
However, when I remove enctype="multipart/form-data", I don't have the file data in my terminal, nor does the image upload to the separate folder. However I DO! get the image data in my mongoDB. This is such a weird problem. Can anyone help?
Also, sorry for the amount of code I have just unleashed. If anyone actually takes the time to answer this then thank you!
Routes
const express = require('express');
const router = express.Router();
const blogController = require('../controllers/blogController')
const multer = require('multer');
const storage = multer.diskStorage({
//destination for files
destination: function (request, file, callback) {
callback(null, './uploads/');
},
//add back the extension
filename: function (request, file, callback) {
callback(null, file.originalname);
},
});
const upload = multer({
storage: storage,
});
router.get('/create', blogController.blog_create_get);
router.get('/', blogController.blog_home);
router.post('/', upload.single('myImage') ,blogController.blog_create_post);
router.get('/:id', blogController.blog_details);
router.delete('/:id', blogController.blog_delete_post);
module.exports = router
Controller code
const blog_create_post = (req, res) => {
console.log(req.file);
const blog = new Blog(req.body, {
})
blog.save()
.then(() => {
res.redirect('/blogs')
})
.catch((err) => {
console.log(err);
})
}
Schema
image: {
data: Buffer,
contentType: String
},
const Blog = mongoose.model('Blog', blogSchema)
module.exports = Blog;
Midleware
// Static Files | Middleware
app.use(express.static('Public'));
app.use(express.urlencoded({ extended: true }));
app.use(morgan('dev'))
app.use('/uploads',express.static('uploads'))
HTML form
<form action="/blogs" enctype="multipart/form-data" method="POST">
<label for="image">Select image:</label>
<input type="file" id="image" name="myImage" accept="image/*">
<input type="submit" value = "Upload Photo">
Multer is triggered only when the enctype of your form is enctype="multipart/form-data". Example from their doc:
<form action="/profile" method="post" enctype="multipart/form-data">
<input type="file" name="avatar" />
</form>
When you don't provide this enctype your req object contains form data in text, and then it is saved to your database, of course.
In order to save binary data to MongoDB you need to open a file designated by
filename: 'photo_2021-12-27_20-07-58.jpg',
path: 'uploads\\photo_2021-12-27_20-07-58.jpg',
and save it appropriately (as text or binary depending on the format and reqs) to the mongodb. To read file check this answer
I wanted to upload images using nodeJS and multer, so I did the following:
Below is my multer configuration:
var multer = require('multer');
var storage = multer.diskStorage({
//Setting up destination and filename for uploads
destination: function (req, file, cb) {
cb(null, 'uploads/');
},
filename: function (req, file, cb) {
cb(null, Date.now() + file.originalname);
}
});
var upload = multer({
storage: storage,
limits:{
fieldSize: 1024*1024*6,
}
});
Below is my route to upload image:
router.post('/designer', upload.single('designerImage'), async (req, res) => {
console.log(req.file);
//rest of the code which is not needed for my query
})
It works perfectly fine when I POST the file using form-data key of type file using POSTMAN. But when I try to send it using a HTML form input, req.file comes out to be undefined and no file gets uploaded to the uploads folder. Below is my HTML form code:
<form action="/designer" method="POST">
<input type="file" name="designerImage">
<form>
What is the solution to this problem? I've spend hours but couldn't get to a solution.
multer only parses multipart/form-data requests, so you need to add enctype="multipart/form-data" to your form
<form action="/designer" method="POST" enctype="multipart/form-data">
<input type="file" name="designerImage">
<form>
I am using Multer to save files I upload through a form but I do not know why my code saves it as a weird name and without extension and I have just used the code from the documentation.
server.js:
const multer = require('multer');
const app = express();
var upload = multer({ dest: 'uploads/' })
app.post('/file', upload.single('filesToAttach'), function (req, res, next) {
console.log(req.file);
loadUserPage(req, res);
})
userPage.ejs:
<form action="/file" method="post" enctype="multipart/form-data">
<div id="frm-attachments">
<div>
<h3>Attachments</h3>
<div>
<input type="file" id="attachFiles" name="filesToAttach" />
<input type="submit" value="Attach">
</div>
<div id="frm-attach-files">
Attached files
<div>
<textarea id="field-attached-files" class="large-textbox" name="attached-files" spellcheck="true" rows="10" cols="50" tabindex="4" disabled="true"></textarea>
</div>
</div>
</div>
</div>
</form>
When I click on the submit button, a new file appear in the folder uploads which is supposed to have the same name and same extension as the file I uploaded in the form, but it has this name instead:
And if I try to print out(req.file), I see this:
Why is this happening? I do not even understand why they write the wrong code in the documentation...
You can set it externally,
Try this,
const multer = require('multer');
const app = express();
var storage = multer.diskStorage({
destination: 'uploads/',
filename: function(req, file, callback) {
callback(null, file.originalname);
}
});
var upload = multer({ storage: storage })
app.post('/file', upload.single('filesToAttach'), function (req, res, next) {
console.log(req.file);
loadUserPage(req, res);
})
You should make a unique name to save your file "generate a random string" and concat this this with the mimetype of your file. as you can see mimetype is already present in the req.file ,
function getFileExtension(mimeType){
if ( mimeType=== 'image/png') {
return '.png';
}
else if ( mimeType=== 'image/jpg') {
return '.jpg';
}
else if ( mimeType=== 'image/gif') {
return '.gif';
}
else {
return '.jpeg';
}
}
If you ae working on images this is the a utility function pass req.mimetype to this and concat its return value to your generated name
I am trying to build an application that consists of uploading a file(such as an image) and posting it.
this is what I have done so far:
var express = require('express');
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './public/img');
},
filename: function (req, file, cb){
cb(null, file.originalname + '-' + Date.now());
}
});
var upload = multer({storage: storage});
So this code above will save the files I upload them in a folder called 'img'
module.exports = function(app){
app.get('/', function(req, res){
res.render('index');
});
app.post('/upload', upload.single('file'), function(req, res){
res.send(req.file);
});
}
Now in the last post request I get all the metadata information about the file in 'req.file'. I wanted to get the file and post it if someone, for instance, makes this request:
app.get('/postedfiles', function(req, res){});
should I save them in a database or something?
Not really, it saves inside your computer, inside the directory that you choose.
This is the plain html form for the multer upload.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<form accept="image/x-png,image/gif,image/jpeg" enctype="multipart/form-data" action="/profile" method="post">
<input type="file" name="avatar" value="">
<input type="submit" name="" value="ssss">
</form>
</body>
</html>
This is our backend code. Inside storage, I choose where to upload the files, which is under /upload directory, and give them file names of that current time. We declare out upload variable for set up, and then we use upload.single('avatar') while we're getting a post request, we declare it right before the callback. What avatar here is that it's the file name from out html form inside input tag. And in the callback we can get to our file by using req.file. The module saves the file this way, very easy to use.
var express = require('express')
var multer = require('multer')
var app = express()
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, __dirname + '/uploads') //you tell where to upload the files,
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now() + '.png')
}
})
var upload = multer({storage: storage,
onFileUploadStart: function (file) {
console.log(file.originalname + ' is starting ...')
},
});
app.set('view engine', 'ejs');
app.get('/', function(req, res, next){
res.render('mult'); //our html document
})
app.post('/profile', upload.single('avatar'), function (req, res, next) {
// req.file is the `avatar` file
console.log(req.file);
return false;
})
Make sure, you give the images and extension of either png or jpeg, or whatever you want to use, otherwise it will not be considered as an image in the computer.
Update on your question
If you want to show the client the image without refreshing the page, just use AJAX with a get request on the client browser. You can upload the files inside your web server or to a web server and retrieve images from there. For example, my profile picture in stackoverflow is saved here
You can use params in a get request to receive all the files from server.
For example, imagine a client making a get request to /uploads/imageOfApet.png.
app.get('/uploads/:theImageName', function(req, res){
console.log(req.params.theImageName); //returns the imageOfApet.png
var theName = req.params.theImageName; //imageOfApet.png
res.sendFile(__dirname + "/uploads/" + theName); //Sending the user the file
})
I'm trying to make a web app that sends MMS using the Twilio API. Uploading an image from my local machine works perfectly. I'm using multer to save the image.
After saving the image using multer I want to send it via MMS using Twilio but I keep getting this error in the twilio monitor
Error: 12300 - Invalid Content-Type
This is my form:
<form method="post" encType="multipart/form-data" action="/upload">
<input type="file" name="imageFile" />
<button type="submit">Send</button>
</form>
My server.js:
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '/uploads');
},
filename: function (req, file, cb) {
cb(null, `${file.fieldname}-${Date.now()}.png`);
}
});
var upload = multer({ storage: storage });
app.post('/upload', upload.single('imageFile'), function (req, res, next) {
var user = ref.getAuth();
var file = req.file.filename;
client.messages.create({
from: twilioNumber,
to: 1234567890,
mediaContentType: 'image/png',
mediaUrl: `http://example.com/uploads/${file}`
}, function(err, message) {
if(err) {
console.log('Error!', err);
} else {
console.log('Message SID:', message.sid);
}
}
});
As you can see I'm including the Content-Type inside client.messages.create. I also wished I don't get redirected to /upload route every time I upload an image.