I'm new to NodeJS, I'm developing app where I have created registeration form. To upload images, I'm using multer. And for form validation I'm using express-validator. The issue with me is that, before form validation, file has upload. So, if user hasn't created account because of some validation errors, but file goes upload. The problem is that I get file upload for each form submition no matter, account has successfully created or not.
What I want to do?
I want save file only when user has successfully created account. So, is there anyway to use multer inside callback, so when my form validations are done, then files goes upload. I can't use express-validation middleware between multer midleware and final callback, because express-validation passes it's errors to next call back.
Here is my some code
router.post('/registeration', multerMiddleware, validationMiddleware, finalCallback)
validationMiddleware is an array.
var multer = require('multer');
var multerMiddleware= multer({dest: './profile-images', fileFilter: userRegisteration.fileFilter}).single('profileImage');
var validationMiddleware = [check(...), check(...),...]
var finalCallback = function (req, res, next) {
// code is here
}
Express router executes the middlewares in the same sequence you mount
them
router.post('/registeration', multerMiddleware, validationMiddleware, finalCallback)
So, your multerMiddleware is executed ( and hence saved the file ) before your validationMiddleware has done the validation.
Change the code to:
router.post('/registeration', validationMiddleware,multerMiddleware, finalCallback)
So, multerMiddleware will only save file once the request is validated
Related
I want to create file uploading web service with jwt Authentication such that peoples can upload there files to /upload route and I will use cloudinary service in my server to actually store them. User can also get their files using filename with /getfile route. Is there something else I should add in my project?
In order for the express server to be able to take a file as an input I would use the package Express file-upload in order to achieve this. The docs are super simple for this one.
Inside of your server.js file:
// setting temp files location
app.use(fileUpload({
useTempFiles : true,
tempFileDir : '/tmp/'
}));
upload route:
app.post('/upload', function(req, res) {
console.log(req.files.foo); // the uploaded file object
res.download('/report-12345.pdf')
});
This file obeject caqn then be used to save the file wherever you desire.
For sending the file back to the user Express also has a feature for this which is documented here
getfile route:
app.get('/getfile', function(req, res) {
// whatever file to be downloaded here
res.download('/report-12345.pdf')
});
Hope that's what you were asking for. Thanks!
My Angular app sends a FormGroup to a Node.js server & then sends that form content via an Email.
At the moment, I can populate the email body like so:
<tr>
<th>Town</th><td>${content['formBody']['personalInfo']['town']}</td>
</tr>
and so on...
But, my form also has a File Upload control which I want to use to add file attachments to the email also.
Here is what I have at the moment:
<td>${content['formBody']['send']['fileUpload']}</td>
But instead of the actual selected file, "object Object" is appearing in the email body currently.
Is there a way I can attach the selected files to the email using the above approach, or is there a different way? Thanks a lot
What are you using in Node.js for getting the files?
A few months ago I needed to upload files and used Multer, a npm package for handling formdata files in node js. With it, you can use the files received on the backend and put it on the email.
In the frontend file
//Method to do the request
superagent
.post(/register")
.attach("avatar", uploadedImage)
uploadedImage has the image content that you get in the VueJS component
In the backend file
var multer = require('multer')
var upload = multer({ dest: 'uploads/' })
import fs from 'fs-extra'
router.post('/register', upload.single('avatar'), (req, res, next) => {
return fs.readFile(req.file.path)
.then(content => {
// The content of the file
})
}
For more information, here you have the answer Accessing data sent as FormData using Axios
Does it help?
They way Multer works on top of express is wired!, why Multer should precede the controller in the chain of Middlewares, which which by design causes the server to upload stuff before the DB operation is even checked?
For instance if there was a post operation to articles, and it contains a bunch of fields one of them is a file.
articleModel{title:String,image:String};
router.post('/', multer, articleController.createArticle);
now at the time the request hits, first thing in the chain is to upload the file in the request, but what if an error happened at the execution of the record to the DB like validation or even duplicates, what if I am going to update the article title only? the old files will be uploaded again?
How to make multer upload the files in the response of the http operation callback?
You can indeed make all kind of stuff before Multer actually process the image:
var upload = multer({
dest: 'uploads/',
fileFilter: function (req, file, cb) {
// only images are allowed
var filetypes = /jpeg|jpg|png/;
var mimetype = filetypes.test(file.mimetype);
var extname = filetypes.test(path.extname(file.originalname).toLowerCase());
if (mimetype && extname) {
return cb(null, true);
}
cb("Error");
}
}).single('localImg');
app.post('/api/file', checkBody, auth, uploadFile, controller.aController);
Take this code for example, you can make all kind of middleware actions BEFORE multer process your file, but multer is a library to process multipart/form-data, not files only, people use multipart for sending files mainly but you can send all kind of data too and it will append them to the body (req.body)
Your question is: "Why multer should upload files before any operation?"
You can execute multer when ever you want, but multer will process the request and get your data into the body. Unless you don't need the body data first hand, you need multer to be in the first middleware.
Your other question is: "what if I am going to update the article title only? the old files will be uploaded again?"
No, it will be uploaded once, if there is any problem with the database, any error or reject, you can always use the filesystem (fs) to remove the file from your server, if you already upload it to a third party system, you can delete it.
Hope it helps
I am using dropzone to upload the file. On the server side I am using node and expressjs. I am also using multer as the file handling middleware.
dropzone makes a call to one endpoint to save the file on the server.
On the server side, I created an endpoint to handle the file:
exports.saveFile = function (req, res) {
console.log(req.files);
return res.status(200);
//I have not added any file save logic here
};
This is how I have configured multer
var app = express();
var server = require('http').createServer(app);
app.use(multer({ dest: './uploads/'}));
Looks like multer automatically saves the file into the uploads folder.
Problem: Even though the file is saved on the server, the request remains in pending state on the client side.
How can I return success response from the server to the client?
Do I need to add some code on the endpoint I have created or I need to add required logic under onFileUploadComplete() given by multer?
You need an Express route for your form post that will finish the http request. The multer middleware will process the file uploads and add them to the request so they are available to a route handler, but you need to have a route for the form post.
From the multer example on this page, you can do something like this for your route:
app.post('/myform', function(req, res){
console.log(req.body); // form fields
console.log(req.files); // form files
res.status(204).end()
});
I should implement an upload form
I thought of using bodyparser but I read
http://andrewkelley.me/post/do-not-use-bodyparser-with-express-js.html
so what's the way to upload a file with express using the mean stack ?
may be formidable or other modules ?
That warning is specifically against adding the express.bodyparser middleware to your entire stack as it adds express.multipart to all POST endpoints and therefore file uploads are automatically accepted at all POST endpoints. By default the framework automatically saves any uploaded files to /tmp and so unless you are cleaning them up an attacker could flood your disk with uploaded files.
If you want to avoid using additional modules, what you should do is implement express.multipart on the endpoint(s) where you want to allow file uploads. Here's what I'm talking about:
var express = require("express")
, app = express();
// middleware (no bodyparser here)
app.use(express.json());
app.use(express.urlencoded());
// average GET endpoint
app.get("/", function(req,res) {
res.send('ok');
});
// average POST endpont
app.post("/login", function(req,res) {
res.send('ok');
});
// File upload POST endpoint
app.post('/upload', express.multipart, function(req, res) {
//File upload logic here
//Make sure to delete or move the file accordingly here, otherwise files will pile up in `/tmp`
});
Note the inclusion of express.multipart in the file upload endpoint. This endpoint will now process multipart file uploads, and assuming you handle them correctly they won't be a threat.
Now, having told you all of this, Connect is moving to deprecate multipart due to this exact issue, but there don't seem to be any plans to add a stream based file upload replacement. What they instead recommend is that you use node-multiparty which uses streams to avoid ever placing a file on disk. However, there don't seem to be any good references I can find for using multiparty as a middleware without saving files though, so you'll have to contact the author of multiparty or take a closer look at the API for implementing it with Express.
I created an example that uses Express & Multer - very simple, avoids all Connect warnings
https://github.com/jonjenkins/express-upload