File upload to a Node JS server - node.js

I am trying to upload a file to my node js server using express.
Here is my nodejs code:
var express=require('express');
var app=express();
var fs=require('fs');
var sys=require('sys');
app.listen(8080);
app.get('/',function(req,res){
fs.readFile('upload.html',function (err, data){
res.writeHead(200, {'Content-Type': 'text/html','Content-Length':data.length});
res.write(data);
res.end();
});
});
app.post('/upload',function(req,res)
{
console.log(req.files);
fs.readFile(req.files.displayImage.path, function (err, data) {
// ...
var newPath = __dirname;
fs.writeFile(newPath, data, function (err) {
res.redirect("back");
});
});
});
My upload.html file:
<html>
<head>
<title>Upload Example</title>
</head>
<body>
<form id="uploadForm"
enctype="multipart/form-data"
action="/upload"
method="post">
<input type="file" id="userPhotoInput" name="displayImage" />
<input type="submit" value="Submit">
</form>
<span id="status" />
<img id="uploadedImage" />
</body>
</html>
I am getting an error that the req.files is undefined.
What could be wrong? The file upload is also not working.

As noted in the docs, req.files, along with req.body are provided by the bodyParser middleware. You can add the middleware like this:
app.use(express.bodyParser());
// or, as `req.files` is only provided by the multipart middleware, you could
// add just that if you're not concerned with parsing non-multipart uploads,
// like:
app.use(express.multipart());

Related

How to upload a file using node js streams and HTML forms?

I want to upload a file using NodeJS streams and HTML forms. I have a simple server.
It is working when I upload the file using Postman. But when I upload through HTML form, the file is uploaded but is not readable. How to do it?
This is index.js:
const app = require('express')();
const fs = require('fs');
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
app.post('/file-upload', (req, res) => {
const filePath = 'uploads/uploaded-file';
const stream = fs.createWriteStream(filePath);
req.pipe(stream);
stream.on('close', () => {
res.send({ status: 'success', filePath })
});
});
// Start server
app.listen(3000, () => console.log("The server is running at localhost:3000"));
This is index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
</head>
<body>
<h1>File Upload</h1>
<form method="post" action="/file-upload" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" name="upload">
</form>
</body>
</html>
This is the postman request screenshot:
As you can see you're trying to upload the file through a form using multipart/form-data whereas you're uploading it as binary in postman.
To fix this you can setup up a multipart/form-data parser on your server side (e.g. using multer), which would look something like this:
const multer = require('multer')
const upload = multer({ dest: 'uploads/' })
// ...
app.post('/file-upload', upload.single('file'), (req, res) => {
res.send({ status: 'success', filePath: req.file.path })
});

Linking HTML button to node.js post

Basic question here: I set up a local server with express and I want to create a file on the server by clicking a HTML button.
Here is the srcServer.js:
var express = require('express');
var path = require('path');
var open = require('open');
var fs = require('fs');
var port = 3000;
var app = express();
app.get('/', function(req, res){
res.sendFile(path.join(__dirname, '../src/index.html'));
});
app.post('/', function(request, respond) {
fs.writeFile('message.txt', 'Hello Node.js', (err) => {
if (err) throw err;
console.log('The file has been saved!');
});
});
app.listen(port, function(err){
if(err){
console.log(err);
}else{
open('http://localhost:' + port);
}
});
And this is the index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
</head>
<body>
<h2>The Button Element</h2>
<form action="" method="post">
<button name="foo" value="send">Send</button>
</form>
</body>
</html>
I am pretty sure the problem is how I am handling the HTML button, but I dont know better. The error I receive when I click on it is: Cannot POST /.
The problem was with the folders- I messed up calling them in the srcServer.js. It works fine after I put all the files in one folder, this way it was easier to do it right.

I'm stuck in rendering templates using express and handlebars

Please, explain me, why my code does not work?
I'm using express width handlebars, for form submit using Jquery Ajax. First render works properly, but second does not. I think that the problem is in nesting 'res.render'. Hope on your answers :-)
app.js
var express = require('express');
var app = express();
var template = require('consolidate');
var handlebars = require('handlebars');
var bodyparser = require('body-parser');
app.use(bodyparser.urlencoded({extended: false}));
app.engine('hbs', template.handlebars);
app.set('view engine', 'hbs');
app.set('views', __dirname);
app.get('/', function(req, res) {
res.render('index', {
myName: 'John'
});
});
app.post('/', function(req, res) {
var obj = {surname: req.body.surname, age: req.body.age};
res.render('Layout.hbs', obj, function(err, html) {
if(err) {
console.log(err);
} else {
console.log(html);
res.render('index.hbs', {
content: html
})
}
}
);
});
app.listen(8080, function() {
console.log('App listening on 8080');
});
index.hbs
<div class="wrapper">
<div class="container">
<p>{{myName}}</p>
</div>
<form action="" name="form" id="form" method="post">
<input id="surname" type="text" name="surname" placeholder="surname"><br/>
<input id="age" type="text" name="age" placeholder="age"><br/>
<input type="submit">
</form>
{{{content}}}
</div>
<script type="text/javascript">
$(document).ready(function() {
$('form').on('submit', function(e) {
e.preventDefault();
var form = $(this);
var surname = form.find('#surname').val();
var age = form.find('#age').val();
$.ajax({
type: 'POST',
data: {surname: surname, age: age},
success: function(res) {
console.log('Success');
},
error: function(err) {
console.log(err);
}
});
});
});
</script>
Layout.hbs
<div class="inner-container">
<h1>{{surname}}</h1>
<h2>{{age}}</h2>
<p>Render</p>
</div>
I think you are right, the problem is with nested res.render. When you call res.render, it renders a html and sends it to the client with a status code of 200.
You can call app.render on root level and res.render only inside a route/middleware. But keep in mind, res.render uses app.render internally to render template files. I don't think there is any need of rendering template separately.
Hope the answer helps you. It would be better for me to answer if I could see the error log that you are getting. If you provide that I would change my answer accordingly.
I think issue with binding delegation event with on() method..
$('form').on('submit', function(e) {
Replace it by
$(document).on('submit','form', function(e)){

how to upload a file in nodejs

HTML code:-
<html>
<body>
<form action="http://localhost:3000/api" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit">
</form>
</body>
</html>
The code in nodeJS is
app.post('/api',function (req, res) {
//JSON.stringify(req.files);
console.log(JSON.stringify(req.files));
var file = req.files.file;
var stream = fs.createReadStream(file.path);
});
I want to print the details of the-files.
I am getting error
TypeError: Cannot read property 'file' of undefined
at /Users/mAddy/Desktop/check1/server.js:27:25
Use multer, as express/connect no longer supports multipart on its own. Also, use the post method on the express/connect app.
After installing multer:
var multer = require('multer');
var upload = multer({dest:'uploads/'});
app.post('/api', upload.single('file'), function (req, res) {
res.sendStatus(200);
});

node.js multi file upload not working

<form action="http://localhost:3000/examples" method="post" enctype="multipart/form-data" accept="application/json">
<input type="text" name ="name">
<input type="text" name ="codedescription">
<input type="file" name ="file">
<input type="submit" value="Upload selected file to server">
</form>
var multer = require('multer');
app.use(multer({ dest: './uploads/',
onFileUploadStart : function(file){
console.log('File recieved:');
console.log(file);
},
onFileUploadData:function (file,data){
console.log('Data recieved');
},
onParseEnd: function(req,next){
next();
}
}));
app.route('/examples').post(users.requiresLogin, examples.create);
exports.create = function(req, res) {
console.log("req.files"+req.files);
console.log("req.name"+req.body.name);
console.log("req.codedescription"+req.body.codedescription);
};
Submit form without enctype="multipart/form-data" is working but I can not get files.
Submit form with enctype="multipart/form-data" is working but I can not get files as well as data.
you can try this
<html>
<head>
<title>FileUpload</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
</head>
<body>
<form id = "uploadForm"
enctype = "multipart/form-data"
action = "http://localhost:3000/api/photo"
method = "post"
>
<input type="file" name="userPhoto" multiple />
<input type="submit" value="Upload Image" name="submit" id="btnUpload">
<span id="spnStatus" />
</form>
<script>
$(document).ready(function(){
$('#btnUpload').click(function(){
$('#spnStatus').empty().text("File is Uploading");
$(this).ajaxSubmit({
error : function(xhr){
status('Error : '+xhr.status);
}
success : function(response){
$('#spnStatus').empty().text(xhr);
}
});
});
});
</script>
</body>
</html>
NodeJS Express
var express = require("../node_modules/express");
var multer = require('../node_modules/multer');
var bodyParser = require("../node_modules/body-parser");
var app = express();
app.use(bodyParser.json());
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './uploads');
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '-' + Date.now());
}
});
var upload = multer({ storage : storage }).array('userPhoto',8);
app.get('/',function(req,res){
res.sendFile(__dirname + "/fileUpload.html");
});
app.post('/api/photo',function(req,res){
upload(req,res,function(err) {
if(err) {
console.log(err);
return res.end("Error uploading file.");
}
res.end("File is uploaded");
});
});
app.listen(3001,function(){
console.log("Working on port 3001");
});
Now you can upload upto 8 files at a time, if you want to upload more than eight, just edit var upload = multer({ storage : storage }).array('userPhoto','LIMITHERE');
#karthik comment, i think you need this as well including after jquery, when you want to use his example:
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery.form/3.51/jquery.form.min.js"></script>

Resources