How to upload files use ExpressJS 4? [duplicate] - node.js

This question already has answers here:
File uploading with Express 4.0: req.files undefined
(13 answers)
Closed 7 years ago.
From ExpressJS 4 API, I find the req.files was invalid.
How to upload files use ExpressJS 4 now?

I just had this issue after upgrading, where req.files was undefined. I fixed it by using multer.
So,
npm install multer
and then in your app.js
var multer = require('multer');
app.use(multer({ dest: './tmp/'}));
I didn't have to change anything else after that and all my old functionality worked.

express.bodyParser is not included in express 4 by default. You must install separately. See https://github.com/expressjs/body-parser
Example :
var bodyParser = require('body-parser');
var app = connect();
app.use(bodyParser());
app.use(function (req, res, next) {
console.log(req.body) // populated!
next();
})
There is also node-formidable
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
res.writeHead(200, {'content-type': 'text/plain'});
res.write('received upload:\n\n');
res.end(util.inspect({fields: fields, files: files}));
});
return;
Here is how I did it:
form = new formidable.IncomingForm();
form.uploadDir = __dirname.getParent() + "/temp/";
form.parse(req, function(err, fields, files) {
var newfile, path, uid, versionName;
uid = uuid.v4();
newfile = __dirname.getParent() + "/uploads/" + uid;
copyFile(files.file.path, newfile, function(err) {
if (err) {
console.log(err);
req.flash("error", "Oops, something went wrong! (reason: copy)");
return res.redirect(req.url);
}
fs.unlink(files.file.path, function(err) {
if (err) {
req.flash("error", "Oops, something went wrong! (reason: deletion)");
return res.redirect(req.url);
}
// done!
// ...
});
});
});

Related

formidable parse callback not be called and no error

I have problem when I use formidable parse function. In my project, I use httpsys (not build-in http module) to create server (for port sharing), and then I send a post request with multipart form data(including string and zip file). Then I want to use formidable to parse request body. But parse function callback does not be called. There is no error. I do not use Express application, but I use Express Router to route my requests. I already use error handler to catch error, but it never be called (form.on('error', function(err) { console.log(err); });). Anyone has same problem? Please help me out, thanks in advance.
// main.js
var router = express.Router();
router.use(function (req, res, next) {
for (var i in req.headers) {
req.headers[i] = querystring.unescape(req.headers[i]);
req.headers[i] = req.headers[i].replace(/\+/g, "");
}
next();
});
//router.use(bodyParser());
router.post('/TestServer/' + 'TestRequest', function(req, res) {
testRequestHandler.execute(req, res);
});
var server = require('httpsys').http().createServer(router);
var port = '80'; // or other port
var listeningPort = 'http://localhost:' + port + '/TestServer/';
server.listen(listeningPort );
// In testRequestHandler
var execute = function(req, res) {
var form = new Formidable.IncomingForm();
form.uploadDir = uploadDir.getPath();
form.encoding = Constants.ENCODING_UTF8;
form.on('file', function(name, file) {console.log('file='+file);});
form.on('error', function(err) { console.log(err); }); // never be called
form.on('aborted', function() { console.log('Aborted'); });
form.parse(req, function(err, fields, files) {
//todo test code
console.log( "parse finished" );
});
}

display data from mongodb with webix

I'm new in javascript and I want to use webix.
I saw the get started and it's Ok...
So, my problem is that I can't display data from mongodb.
This is my server.js
var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
//connect to the mongo
var db = require('mongoskin').db("mongodb://localhost:27017/test", { w: 0});
db.bind('sites');
//create the app instance
var app = express();
//serve static files
app.use(express.static(path.join(__dirname, 'public')));
//parse POST data
app.use(bodyParser.urlencoded({ extended: false }));
// // parse application/json
app.use(bodyParser.json());
function after_update(err, res, record){
if (err){
res.status(500);
res.send({ error:err.toString() });
} else {
res.send(record || {});
}
}
//data loading
app.get('/data', function(req, res){
db.record.find().toArray(function(err, data){
for (var i = 0; i < data.length; i++){
data[i].id = data[i]._id;
delete data[i]._id;
}
res.send(data);
});
});
app.post('/data', function(req, res){
db.record.insert(req.body, function(err, record){
if (err) return res.send({ status:"error" });
res.send({ newid:req.body._id });
});
});
app.put('/data/:id', function(req, res){
db.record.updateById(req.param("id"), req.body, function(err){
if (err) return res.send({ status:"error" });
res.send({});
});
});
app.delete('/data/:id', function(req, res){
db.record.removeById(req.param("id"), req.body, function(err){
if (err) return res.send({ status:"error" });
res.send({});
});
});
app.listen(3000);
and I'm using index.html to display data. Here that it sucks.
my problem is that I can't found the right manner to get the data from my table in mongodb.
I want to display the cars in my DB.
who has an exemple that can help?
Anyone can help please?
Thank you
Try to load the "/data" in the browser. If it shows the valid JSON, check the client-side code of the datatable, it must be something like following
{ view:"datatable", autoConfig:true, url:"/data" }
I see 2 problems in your code (i guess that your collection is "cars" becouse your text):
You are binding a diferent collection than "cars", in the line "db.bind('sites');". You should change for "db.bind('cars');"
You are using the collection "record" to retrieve and write data, in the sentences "db.record.find", "db.record.insert", "db.record.updateById" and "db.record.removeById". You should change for "db.cars.find", "db.cars.insert", "db.cars.updateById" and "db.cars.removeById".
Cheers.

upload image node.js express

I'm trying to upload image to server in node.js and express.
My jade image upload form:
include layout
div.container
h2 Image Upload Form
form#fileUpload(method="post" action="/upload" enctype="multipart/form-data")
label(for="payload") Select a file to upload:
input#payload(type="file" name="myFile" accept="image/*")
br
button#upload Upload
And in my index.js where I handle response and show form are:
router.get('/imageUpload', function(req, res, next){
res.render('imageUpload', { title: 'Image upload form' });
});
router.post("/upload", function(req, res, next){
console.log(req.files);
});
I am getting undefined error when I try to get req.files; I'm new to node so plz help.
Thank you.
Finally image uploading is thanx Lucas Costa for help know i share my code
Step 1. Install formidable from official site formidable
Run command on your prompt
npm install formidable#latest
Step 2. My image upload form in .jade
include layout
div.container
h2 Image Upload Form
form#fileUpload(method="post" action="/upload" enctype="multipart/form-data")
label(for="payload") Select a file to upload:
input#payload(type="file" name="myFile" accept="image/*")
br
button#upload Upload
Step 3. Add module in your file in my case i have index.js
var express = require('express');
var router = express.Router();
var util = require("util");
var fs = require("fs");
var formidable = require('formidable');
var path = require('path');
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express', dataGet: "data" });
});
router.get('/about', function(req, res, next) {
res.render('index', { title: 'C' });
});
router.get('/imageUpload', function(req, res, next){
res.render('imageUpload', { title: 'Image upload form' });
});
router.post("/upload", function(req, res, next){
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
// `file` is the name of the <input> field of type `file`
console.log(files);
res.writeHead(200, {'content-type': 'text/plain'});
res.write('received upload:\n\n');
res.end(util.inspect({fields: fields, files: files}));
});
form.on('error', function(err) {
console.error(err);
});
form.on('progress', function(bytesReceived, bytesExpected) {
var percent_complete = (bytesReceived / bytesExpected) * 100;
console.log(percent_complete.toFixed(2));
});
form.on('end', function(fields, files) {
/* Temporary location of our uploaded file */
var temp_path = this.openedFiles[0].path;
/* The file name of the uploaded file */
var file_name = this.openedFiles[0].name;
/* Location where we want to copy the uploaded file */
var new_location = 'F:/node/expressApp/myAppExpress/public/images/';
fs.readFile(temp_path, function(err, data) {
fs.writeFile(new_location + file_name, data, function(err) {
fs.unlink(temp_path, function(err) {
if (err) {
console.error(err);
} else {
console.log("success!");
}
});
});
});
});
});
router.get('/:username', function(req, res) {
// make somethings with username
var username = req.params.username;
console.log("get username"+ username);
});
module.exports = router;
All done! Hope this will help some one :-)
The undefined is getting because doesn't exists req.files.
Alter to:
console.log(req.body) // or req.body.myFile to get information of the input
For upload image, I suggest you use formidable, somelike this.

Express 3.4.8 Photo uploading issue - how to solve without using bodyParser()?

my code at Gist: https://gist.github.com/yhagio/10654836
I'm new to Express, tried from the example of the book "Node.js in Action - Chapter.9"(Uploading photo).
The author uses Express version "3.4.0" but I used "3.4.8" and I ran into this issue,
The Error message when I try to upload images:
500 TypeError: Cannot read property 'photo' of undefined
routes/photos.js
...
exports.submit = function (dir) {
return function (req, res, next) {
var img = req.files.photo.image; // ---- This 'photo' part is undefined
var name = req.body.photo.name || img.name;
var path = join(dir, img.name);
fs.rename(img.path, path, function (err) {
if (err) { return next(err); };
Photo.create({
name:name,
path:req.name
}, function (err) {
if (err) { return next(err); };
res.redirect('/');
});
});
};
};
but I found that in my app.js (bodyParser() is no longer used since 3.4.8)
app.js(In my code Express 3.4.8)
...
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json()); // Instead of bodyParser()
app.use(express.urlencoded()); // Instead of bodyParser()
...
But in author's code has bodyParser().
app.js(Author uses Express 3.4.0
...
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser()); // This is no longer used in latest version
So, I was wondering if I can fix this issue by using multer (http://expressjs-book.com/forums/topic/replacement-for-bodyparser-connect-multipart/):
app.use(express.json());
app.use(express.urlencoded());
app.use(multer({ dest: './public/photos' })); // I tried this
This didn't solve. Please help me. Thank you.
UPDATE: Solution I figured out
This code worked(routes/photos.js)
exports.submit = function (dir) {
return function(req, res, next){
var form = new multiparty.Form();
form.parse(req, function(err, fields, files){
var img = files.image[0];
var name = fields.name || img.originalFilename;
var path = join(dir, img.originalFilename);
fs.rename(img.path, path, function(err){
if(err){return next(err); };
Photo.create({
name: name,
path: img.originalFilename
}, function(err){
if(err){return next(err); };
res.redirect('/');
});
});
});
};
};
Have you given node-multiparty a try? Here's example usage from the README:
var multiparty = require('multiparty')
, http = require('http')
, util = require('util')
http.createServer(function(req, res) {
if (req.url === '/upload' && req.method === 'POST') {
// parse a file upload
var form = new multiparty.Form();
form.parse(req, function(err, fields, files) {
res.writeHead(200, {'content-type': 'text/plain'});
res.write('received upload:\n\n');
res.end(util.inspect({fields: fields, files: files}));
});
return;
}
// show a file upload form
res.writeHead(200, {'content-type': 'text/html'});
res.end(
'<form action="/upload" enctype="multipart/form-data" method="post">'+
'<input type="text" name="title"><br>'+
'<input type="file" name="upload" multiple="multiple"><br>'+
'<input type="submit" value="Upload">'+
'</form>'
);
}).listen(8080);
The author (Andrew Kelley) recommends avoiding bodyParser, so you're right to avoid it, but multiparty seems to solve a similar issue for me.
The reason it no longer works is because the node-formidable library is no longer included in Express. If you want to continue using formidable, follow these instructions.
The proper way to use body-parser with Express 4.x is:
var express = require('express'),
bodyParser = require('body-parser'),
app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
To access the files:
var formidable = require('formidable'),
form = new formidable.IncomingForm();
exports.submit = function (dir) {
return function (req, res, next) {
form.parse(req, function(err, fields, files) {
// The files object here is what you expected from req.files
});
});
});
Note: if you're trying to use multiple, set:
form.multiples = true;

Uploading images using Node.js, Express, and Mongoose

Please consider newer answers that have more up-to-date information as things have changed over the years!
Since many new Node.js libraries are quickly being rendered obsolete and there are relatively few examples anyways I want to ask about uploading images using:
Node.js (v0.4.1)
Express (1.0.7)
Mongoose (1.1.0).
How have others done it?
I've found: node-formidable, but I am new to uploading images in general so I want to learn general stuff and ways of doing so using Node.js and Express.
I'll answer my own question for the first time. I found an example straight from the source. Please forgive the poor indentation. I wasn't sure how to indent properly when copying and pasting. The code comes straight from Express multipart/form-data example on GitHub.
// Expose modules in ./support for demo purposes
require.paths.unshift(__dirname + '/../../support');
/**
* Module dependencies.
*/
var express = require('../../lib/express')
, form = require('connect-form');
var app = express.createServer(
// connect-form (http://github.com/visionmedia/connect-form)
// middleware uses the formidable middleware to parse urlencoded
// and multipart form data
form({ keepExtensions: true })
);
app.get('/', function(req, res){
res.send('<form method="post" enctype="multipart/form-data">'
+ '<p>Image: <input type="file" name="image" /></p>'
+ '<p><input type="submit" value="Upload" /></p>'
+ '</form>');
});
app.post('/', function(req, res, next){
// connect-form adds the req.form object
// we can (optionally) define onComplete, passing
// the exception (if any) fields parsed, and files parsed
req.form.complete(function(err, fields, files){
if (err) {
next(err);
} else {
console.log('\nuploaded %s to %s'
, files.image.filename
, files.image.path);
res.redirect('back');
}
});
// We can add listeners for several form
// events such as "progress"
req.form.on('progress', function(bytesReceived, bytesExpected){
var percent = (bytesReceived / bytesExpected * 100) | 0;
process.stdout.write('Uploading: %' + percent + '\r');
});
});
app.listen(3000);
console.log('Express app started on port 3000');
Since you're using express, just add bodyParser:
app.use(express.bodyParser());
then your route automatically has access to the uploaded file(s) in req.files:
app.post('/todo/create', function (req, res) {
// TODO: move and rename the file using req.files.path & .name)
res.send(console.dir(req.files)); // DEBUG: display available fields
});
If you name the input control "todo" like this (in Jade):
form(action="/todo/create", method="POST", enctype="multipart/form-data")
input(type='file', name='todo')
button(type='submit') New
Then the uploaded file is ready by the time you get the path and original filename in 'files.todo':
req.files.todo.path, and
req.files.todo.name
other useful req.files properties:
size (in bytes)
type (e.g., 'image/png')
lastModifiedate
_writeStream.encoding (e.g, 'binary')
You can configure the connect body parser middleware in a configuration block in your main application file:
/** Form Handling */
app.use(express.bodyParser({
uploadDir: '/tmp/uploads',
keepExtensions: true
}))
app.use(express.limit('5mb'));
See, the best thing you can do is to just upload the image to the disk and save the URL in MongoDB. Rest when you retrieve the image again. Just specify the URL, and you will get an image. The code for uploading is as follows.
app.post('/upload', function(req, res) {
// Get the temporary location of the file
var tmp_path = req.files.thumbnail.path;
// Set where the file should actually exists - in this case it is in the "images" directory.
target_path = '/tmp/' + req.files.thumbnail.name;
// Move the file from the temporary location to the intended location
fs.rename(tmp_path, target_path, function(err) {
if (err)
throw err;
// Delete the temporary file, so that the explicitly set temporary upload dir does not get filled with unwanted files.
fs.unlink(tmp_path, function() {
if (err)
throw err;
//
});
});
});
Now save the target path in your MongoDB database.
Again, while retrieving the image, just extract the URL from the MongoDB database, and use it on this method.
fs.readFile(target_path, "binary", function(error, file) {
if(error) {
res.writeHead(500, {"Content-Type": "text/plain"});
res.write(error + "\n");
res.end();
}
else {
res.writeHead(200, {"Content-Type": "image/png"});
res.write(file, "binary");
}
});
Try this code.It will help.
app.get('/photos/new', function(req, res){
res.send('<form method="post" enctype="multipart/form-data">'
+ '<p>Data: <input type="filename" name="filename" /></p>'
+ '<p>file: <input type="file" name="file" /></p>'
+ '<p><input type="submit" value="Upload" /></p>'
+ '</form>');
});
app.post('/photos/new', function(req, res) {
req.form.complete(function(err, fields, files) {
if(err) {
next(err);
} else {
ins = fs.createReadStream(files.photo.path);
ous = fs.createWriteStream(__dirname + '/directory were u want to store image/' + files.photo.filename);
util.pump(ins, ous, function(err) {
if(err) {
next(err);
} else {
res.redirect('/photos');
}
});
//console.log('\nUploaded %s to %s', files.photo.filename, files.photo.path);
//res.send('Uploaded ' + files.photo.filename + ' to ' + files.photo.path);
}
});
});
if (!module.parent) {
app.listen(8000);
console.log("Express server listening on port %d, log on to http://127.0.0.1:8000", app.address().port);
}
You can also use the following to set a path where it saves the file.
req.form.uploadDir = "<path>";
I created an example that uses Express and Multer. It is very simple and avoids all Connect warnings
It might help somebody.
Again if you don't want to use bodyParser, the following works:
var express = require('express');
var http = require('http');
var app = express();
app.use(express.static('./public'));
app.configure(function(){
app.use(express.methodOverride());
app.use(express.multipart({
uploadDir: './uploads',
keepExtensions: true
}));
});
app.use(app.router);
app.get('/upload', function(req, res){
// Render page with upload form
res.render('upload');
});
app.post('/upload', function(req, res){
// Returns json of uploaded file
res.json(req.files);
});
http.createServer(app).listen(3000, function() {
console.log('App started');
});
For Express 3.0, if you want to use the formidable events, you must remove the multipart middleware, so you can create the new instance of it.
To do this:
app.use(express.bodyParser());
Can be written as:
app.use(express.json());
app.use(express.urlencoded());
app.use(express.multipart()); // Remove this line
And now create the form object:
exports.upload = function(req, res) {
var form = new formidable.IncomingForm;
form.keepExtensions = true;
form.uploadDir = 'tmp/';
form.parse(req, function(err, fields, files){
if (err) return res.end('You found error');
// Do something with files.image etc
console.log(files.image);
});
form.on('progress', function(bytesReceived, bytesExpected) {
console.log(bytesReceived + ' ' + bytesExpected);
});
form.on('error', function(err) {
res.writeHead(400, {'content-type': 'text/plain'}); // 400: Bad Request
res.end('error:\n\n'+util.inspect(err));
});
res.end('Done');
return;
};
I have also posted this on my blog, Getting formidable form object in Express 3.0 on upload.
I know that the original question related to specific versions, but it also referred to the "latest" - #JohnAllen 's post is no longer relevant due to Expressjs bodyParser and connect-form
This demonstrates the easy to use in-built bodyParser():
/**
* Module dependencies.
*/
var express = require('express')
var app = express()
app.use(express.bodyParser({ keepExtensions: true, uploadDir: '/home/svn/rest-api/uploaded' }))
app.get('/', function(req, res){
res.send('<form method="post" enctype="multipart/form-data">'
+ '<p>Image: <input type="file" name="image" /></p>'
+ '<p><input type="submit" value="Upload" /></p>'
+ '</form>');
});
app.post('/', function(req, res, next){
res.send('Uploaded: ' + req.files.image.name)
return next()
});
app.listen(3000);
console.log('Express app started on port 3000');
There's my method to multiple upload file:
Nodejs :
router.post('/upload', function(req , res) {
var multiparty = require('multiparty');
var form = new multiparty.Form();
var fs = require('fs');
form.parse(req, function(err, fields, files) {
var imgArray = files.imatges;
for (var i = 0; i < imgArray.length; i++) {
var newPath = './public/uploads/'+fields.imgName+'/';
var singleImg = imgArray[i];
newPath+= singleImg.originalFilename;
readAndWriteFile(singleImg, newPath);
}
res.send("File uploaded to: " + newPath);
});
function readAndWriteFile(singleImg, newPath) {
fs.readFile(singleImg.path , function(err,data) {
fs.writeFile(newPath,data, function(err) {
if (err) console.log('ERRRRRR!! :'+err);
console.log('Fitxer: '+singleImg.originalFilename +' - '+ newPath);
})
})
}
})
Make sure your form has enctype="multipart/form-data"
I hope this gives you a hand ;)
Here's a way to upload your images using the formidable package, which is recommended over bodyParser in later versions of Express. This also includes the ability to resize your images on the fly:
From my website: Uploading and Resizing Images (on the fly) With Node.js and Express.
Here's the gist:
var express = require("express"),
app = express(),
formidable = require('formidable'),
util = require('util')
fs = require('fs-extra'),
qt = require('quickthumb');
// Use quickthumb
app.use(qt.static(__dirname + '/'));
app.post('/upload', function (req, res){
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
res.writeHead(200, {'content-type': 'text/plain'});
res.write('received upload:\n\n');
res.end(util.inspect({fields: fields, files: files}));
});
form.on('end', function(fields, files) {
/* Temporary location of our uploaded file */
var temp_path = this.openedFiles[0].path;
/* The file name of the uploaded file */
var file_name = this.openedFiles[0].name;
/* Location where we want to copy the uploaded file */
var new_location = 'uploads/';
fs.copy(temp_path, new_location + file_name, function(err) {
if (err) {
console.error(err);
} else {
console.log("success!")
}
});
});
});
// Show the upload form
app.get('/', function (req, res){
res.writeHead(200, {'Content-Type': 'text/html' });
/* Display the file upload form. */
form = '<form action="/upload" enctype="multipart/form-data" method="post">'+ '<input name="title" type="text" />
'+ '<input multiple="multiple" name="upload" type="file" />
'+ '<input type="submit" value="Upload" />'+ '</form>';
res.end(form);
});
app.listen(8080);
NOTE: This requires Image Magick for the quick thumb resizing.
It will become easy to store files after converting in string you just have to convert string in image in your frontend
convert image in to base64 string using this code in your api and also don't forgot to delete file from upload folder
"img": new Buffer.from(fs.readFileSync(req.file.path)).toString("base64")
to delete the file
let resultHandler = function (err) {
if (err) {
console.log("unlink failed", err);
} else {
console.log("file deleted");
}
}
fs.unlink(req.file.path, resultHandler);
at your routes import multer
`multer const multer = require('multer');
const upload = multer({ dest: __dirname + '/uploads/images' });`
Add upload.single('img') in your request
router.post('/fellows-details', authorize([Role.ADMIN, Role.USER]),
upload.single('img'), usersController.fellowsdetails);
OR
If you want save images in localstorage and want save path in database you can try following approach
you have to install first the fs-extra which will create folder. I am creating separate folders by id's if you want to remove it you can remove it. and
to save path of image where it is uploaded add this code in your api or controller you are using to save image and and add it in database with other data
let Id = req.body.id;
let path = `tmp/daily_gasoline_report/${Id}`;
create separate folder for multer like multerHelper.js
const multer = require('multer');
let fs = require('fs-extra');
let storage = multer.diskStorage({
destination: function (req, file, cb) {
let Id = req.body.id;
let path = `tmp/daily_gasoline_report/${Id}`;
fs.mkdirsSync(path);
cb(null, path);
},
filename: function (req, file, cb) {
// console.log(file);
let extArray = file.mimetype.split("/");
let extension = extArray[extArray.length - 1];
cb(null, file.fieldname + '-' + Date.now() + "." + extension);
}
})
let upload = multer({ storage: storage });
let createUserImage = upload.array('images', 100);
let multerHelper = {
createUserImage,
}
module.exports = multerHelper;
In your routes import multerhelper file
const multerHelper = require("../helpers/multer_helper");
router.post(multerHelper. createUserImage , function(req, res, next) {
//Here accessing the body datas.
})

Resources