Twilio + Express Multer - node.js

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.

Related

No image found after uploading it with Muller

I am making a small script to upload a photo and save it to local storage. I'm using Express and Muller for this.
I have an html page with an upload field (see below). As soon as I press the 'upload photo' button he sends the photo to the endpoint '/upload'. Here he should save the photo on my computer under the name 'image.jpg' only when it comes in the post the 'req.file' is empty.
I just wonder what is going wrong? Am I missing something?
App.js
const express = require("express");
const multer = require("multer");
const helpers = require("./helpers");
const app = express();
const port = process.env.PORT || 3000;
app.use(express.static(__dirname + "/"));
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "uploads/");
},
filename: function (req, file, cb) {
cb(null, "image.jpg");
},
});
app.listen(port, () => console.log(`Listening on port ${port}...`));
app.post("/upload", (req, res) => {
let upload = multer({
storage: storage,
fileFilter: helpers.imageFilter,
}).single("image");
upload(req, res, function (err) {
if (req.fileValidationError) {
return res.send(req.fileValidationError);
} else if (!req.file) {
return res.send("Please select an image to upload");
} else if (err instanceof multer.MulterError) {
return res.send(err);
} else if (err) {
return res.send(err);
}
res.send(
`You have uploaded this image: <hr/><img src="${req.file.path}" width="500"><hr />Upload another image`
);
});
});
Helpers.js
const imageFilter = function(req, file, cb) {
// Accept images only
if (!file.originalname.match(/\.(jpg|JPG|jpeg|JPEG|png|PNG|gif|GIF)$/)) {
req.fileValidationError = 'Only image files are allowed!';
return cb(new Error('Only image files are allowed!'), false);
}
cb(null, true);
};
exports.imageFilter = imageFilter;
HTML Page
<form action="/upload" enctype="multipart/form-data" method="POST">
<input type="file" name="image" accept="image/*" />
<input type="submit" value="Upload Photo" />
</form>
It went wrong at the 'const storage'. I filled in the wrong file path. But it strange that the req.file was empty ... Anyway, it works!

Uploading multiple image files with multer from different input fields

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/

req.file is undefined when I upload image using multer and html input form

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>

Multer Doesn't Save Images on Disk In Any Way

It simply doesn't save anything to the destination folder i specified.
i tried {storage:storage} instead of {dest: 'storage/'} but it didn't work either.
the image data is actually sent to the server as its console logged. and the dest i specified is created by default but remain empty.
const express = require('express');
const app = express();
const multer = require('multer');
let storage = multer.diskStorage({
destination: '/public/my-uploads',
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
});
const upload = multer({dest:'storage/'}).single('file');
app.post('/upload', upload, (req , res) => {
console.log(req.files) // this does log the uploaded image data.
})
***** EDIT ******
HTML
<form onSubmit={this.upload} enctype='multipart/form-data'>
<input type='file' name='image' />
<input type='submit' value='upload' />
</form>
JS
upload(e){
e.preventDefault();
const file = e.target[0].files[0];
console.log(file)
const fm = new FormData();
fm.append('file', file);
console.log(fm)
axios.post('/upload', fm);
}
POSTMAN
Try to catch the error my calling the middleware yourself:
var upload = multer().single('avatar')
app.post('/upload', function (req, res) {
upload(req, res, function (err) {
if (err) {
// An error occurred when uploading
return
}
// Everything went fine
})
})
Also, change the storage to this:
let storage = multer.diskStorage({
destination: function(req, file, ca) {
cb(null, '/public/my-uploads');
}
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
});
It's been a while, the issue was that I wasn't using the multer middleware at all so the callback code for handling the image was never executed.
I didn't know much about how express worked back then.
Seems you are not using the storage variable and use a function for the destination key, as written in the documentation, also you need to pass your file in the input field named field otherwise multer can't store the file, create an storage folder on the same level as the code :
const http = require('http')
const port = 3000
const express = require('express');
const app = express();
const multer = require('multer');
const server = http.createServer(app)
let storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './storage')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
});
const upload = multer({ storage }).single('file');
app.post('/upload', upload, (req, res) => {
console.log(req.files) // this does log the uploaded image data.
})
// bind the server on port
server.listen(port, (err) => {
if (err) {
return console.log('something bad happened', err)
}
console.log(`server is listening on ${port}`)
})
The name of the "single" in ...single('file') must match the name in the input (containing the file) <input type="file" name='image' /> - and it does not in your example.
Change the multer-part to this ...single('image') - as in the input name='image'
Try this File Storage For Save image in Local
const fileStorage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "images");
},
filename: (req, file, cb) => {
cb(
null,
new Date().toISOString().replace(/:/g, "-") + "-" + file.originalname
);
},
});

How do I post an image with Nodejs and Multer?

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
})

Resources