node js normal file upload code shows error while executing - javascript

I am trying a simple node.js file upload code for test purpose by using express and multer modules.My code look for html like :-
<html>
<head>
<title>File Uploading Form</title>
</head>
<body>
<h3>File Upload:</h3>
Select a file to upload: <br />
<form action="http://127.0.0.1:8081/file_upload" method="POST"
enctype="multipart/form-data">
<input type="file" name="file" size="50" />
<br />
<input type="submit" value="Upload File" />
</form>
</body>
and my server.js code look like :-
var express = require('express');
var app = express();
var fs = require("fs");
var bodyParser = require('body-parser');
var multer = require('multer');
app.use(express.static('public'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(multer({ dest: '/tmp/'}));
app.get('/index.html', function (req, res) {
res.sendFile( __dirname + "/" + "index.html" );
});
app.post('/file_upload', function (req, res) {
console.log(req.files.file.name);
console.log(req.files.file.path);
console.log(req.files.file.type);
var file = __dirname + "/" + req.files.file.name;
fs.readFile( req.files.file.path, function (err, data) {
fs.writeFile(file, data, function (err) {
if( err ){
console.log( err );
}else{
response = {
message:'File uploaded successfully',
filename:req.files.file.name
};
}
console.log( response );
res.end( JSON.stringify( response ) );
});
});
});
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
});
Now while I run the server.js from command prompt like :- node server.js My server doesn't get started and it throws some error like image :-

SOuřaan Gřg,
Your line, var multer = require('multer'); is returning and object, not the middleware function. There are three middleware functions you can use.
Check out the docs.
In case you need to handle a text-only multipart form, you can use any of the multer methods (.single(), .array(), fields()).
.single(fieldname) Accept a single file with the name fieldname. The single file will be stored in req.file.
.array(fieldname[, maxCount]) Accept an array of files, all with the
name fieldname. Optionally error out if more than maxCount files are
uploaded. The array of files will be stored in req.files.
.fields(fields) Accept a mix of files, specified by fields. An object
with arrays of files will be stored in req.files.
You must change app.use(multer({ dest: '/tmp/'}));. You are passing an object.
Also according to the docs:
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.
You should be assigning the middleware to route in where you are handling the upload. For your case you could do the following:
var upload = multer({ dest: '/tmp/' });
app.post('/file_upload', upload.single('file'), function (req, res, next) {
// req.file is the `file` file
// req.body will hold the text fields, if there were any
})

Related

req.files giving NULL after ajax call, not correct file name [duplicate]

I'm attempting to get a simple file upload mechanism working with Express 4.0 but I keep getting undefined for req.files in the app.post body. Here is the relevant code:
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
//...
app.use(bodyParser({ uploadDir: path.join(__dirname, 'files'), keepExtensions: true }));
app.use(methodOverride());
//...
app.post('/fileupload', function (req, res) {
console.log(req.files);
res.send('ok');
});
.. and the accompanying Pug code:
form(name="uploader", action="/fileupload", method="post", enctype="multipart/form-data")
input(type="file", name="file", id="file")
input(type="submit", value="Upload")
Solution
Thanks to the response by mscdex below, I've switched to using busboy instead of bodyParser:
var fs = require('fs');
var busboy = require('connect-busboy');
//...
app.use(busboy());
//...
app.post('/fileupload', function(req, res) {
var fstream;
req.pipe(req.busboy);
req.busboy.on('file', function (fieldname, file, filename) {
console.log("Uploading: " + filename);
fstream = fs.createWriteStream(__dirname + '/files/' + filename);
file.pipe(fstream);
fstream.on('close', function () {
res.redirect('back');
});
});
});
The body-parser module only handles JSON and urlencoded form submissions, not multipart (which would be the case if you're uploading files).
For multipart, you'd need to use something like connect-busboy or multer or connect-multiparty (multiparty/formidable is what was originally used in the express bodyParser middleware). Also FWIW, I'm working on an even higher level layer on top of busboy called reformed. It comes with an Express middleware and can also be used separately.
Here is what i found googling around:
var fileupload = require("express-fileupload");
app.use(fileupload());
Which is pretty simple mechanism for uploads
app.post("/upload", function(req, res)
{
var file;
if(!req.files)
{
res.send("File was not found");
return;
}
file = req.files.FormFieldName; // here is the field name of the form
res.send("File Uploaded");
});
1) Make sure that your file is really sent from the client side. For example you can check it in Chrome Console:
screenshot
2) Here is the basic example of NodeJS backend:
const express = require('express');
const fileUpload = require('express-fileupload');
const app = express();
app.use(fileUpload()); // Don't forget this line!
app.post('/upload', function(req, res) {
console.log(req.files);
res.send('UPLOADED!!!');
});
It looks like body-parser did support uploading files in Express 3, but support was dropped for Express 4 when it no longer included Connect as a dependency
After looking through some of the modules in mscdex's answer, I found that express-busboy was a far better alternative and the closest thing to a drop-in replacement. The only differences I noticed were in the properties of the uploaded file.
console.log(req.files) using body-parser (Express 3) output an object that looked like this:
{ file:
{ fieldName: 'file',
originalFilename: '360px-Cute_Monkey_cropped.jpg',
name: '360px-Cute_Monkey_cropped.jpg'
path: 'uploads/6323-16v7rc.jpg',
type: 'image/jpeg',
headers:
{ 'content-disposition': 'form-data; name="file"; filename="360px-Cute_Monkey_cropped.jpg"',
'content-type': 'image/jpeg' },
ws:
WriteStream { /* ... */ },
size: 48614 } }
compared to console.log(req.files) using express-busboy (Express 4):
{ file:
{ field: 'file',
filename: '360px-Cute_Monkey_cropped.jpg',
file: 'uploads/9749a8b6-f9cc-40a9-86f1-337a46e16e44/file/360px-Cute_Monkey_cropped.jpg',
mimetype: 'image/jpeg',
encoding: '7bit',
truncated: false
uuid: '9749a8b6-f9cc-40a9-86f1-337a46e16e44' } }
multer is a middleware which handles “multipart/form-data” and magically & makes the uploaded files and form data available to us in request as request.files and request.body.
installing multer :- npm install multer --save
in .html file:-
<form method="post" enctype="multipart/form-data" action="/upload">
<input type="hidden" name="msgtype" value="2"/>
<input type="file" name="avatar" />
<input type="submit" value="Upload" />
</form>
in .js file:-
var express = require('express');
var multer = require('multer');
var app = express();
var server = require('http').createServer(app);
var port = process.env.PORT || 3000;
var upload = multer({ dest: 'uploads/' });
app.use(function (req, res, next) {
console.log(req.files); // JSON Object
next();
});
server.listen(port, function () {
console.log('Server successfully running at:-', port);
});
app.get('/', function(req, res) {
res.sendFile(__dirname + '/public/file-upload.html');
})
app.post('/upload', upload.single('avatar'), function(req, res) {
console.log(req.files); // JSON Object
});
Hope this helps!
Please use below code
app.use(fileUpload());
Just to add to answers above, you can streamline the use of express-fileupload to just a single route that needs it, instead of adding it to the every route.
let fileupload = require("express-fileupload");
...
//Make sure to call fileUpload to get the true handler
app.post("/upload", fileupload(), function(req, res){
...
});
A package installation needs for this functionality, There are many of them but I personally prefer "express-fileupload". just install this by "npm i express-fileupload" command in the terminal and then use this in your root file
const fileUpload = require("express-fileupload");
app.use(fileUpload());
PROBLEM SOLVED !!!!!!!
Turns out the storage function DID NOT run even once.
because i had to include app.use(upload) as upload = multer({storage}).single('file');
let storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './storage')
},
filename: function (req, file, cb) {
console.log(file) // this didn't print anything out so i assumed it was never excuted
cb(null, file.fieldname + '-' + Date.now())
}
});
const upload = multer({storage}).single('file');
I added multer as global middleware before methodOverride middleware,
and it worked in router.put as well.
const upload = multer({
storage: storage
}).single('featuredImage');
app.use(upload);
app.use(methodOverride(function (req, res) {
...
}));
With Formidable :
const formidable = require('formidable');
app.post('/api/upload', (req, res, next) => {
const form = formidable({ multiples: true });
form.parse(req, (err, fields, files) => {
if (err) {
next(err);
return;
}
res.json({ fields, files });
});
});
https://www.npmjs.com/package/formidable
You can use express-fileupload npm package to decode files like
const fileUpload = require('express-fileupload');
app.use(fileUpload({useTempFile: true}))
Note: I am using cloudinary to upload image
enter image description here
express-fileupload looks like the only middleware that still works these days.
With the same example, multer and connect-multiparty gives an undefined value of req.file or req.files, but express-fileupload works.
And there are a lot of questions and issues raised about the empty value of req.file/req.files.

how to Post request base64 encoded Audio blob to Node Express JS [duplicate]

I'm attempting to get a simple file upload mechanism working with Express 4.0 but I keep getting undefined for req.files in the app.post body. Here is the relevant code:
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
//...
app.use(bodyParser({ uploadDir: path.join(__dirname, 'files'), keepExtensions: true }));
app.use(methodOverride());
//...
app.post('/fileupload', function (req, res) {
console.log(req.files);
res.send('ok');
});
.. and the accompanying Pug code:
form(name="uploader", action="/fileupload", method="post", enctype="multipart/form-data")
input(type="file", name="file", id="file")
input(type="submit", value="Upload")
Solution
Thanks to the response by mscdex below, I've switched to using busboy instead of bodyParser:
var fs = require('fs');
var busboy = require('connect-busboy');
//...
app.use(busboy());
//...
app.post('/fileupload', function(req, res) {
var fstream;
req.pipe(req.busboy);
req.busboy.on('file', function (fieldname, file, filename) {
console.log("Uploading: " + filename);
fstream = fs.createWriteStream(__dirname + '/files/' + filename);
file.pipe(fstream);
fstream.on('close', function () {
res.redirect('back');
});
});
});
The body-parser module only handles JSON and urlencoded form submissions, not multipart (which would be the case if you're uploading files).
For multipart, you'd need to use something like connect-busboy or multer or connect-multiparty (multiparty/formidable is what was originally used in the express bodyParser middleware). Also FWIW, I'm working on an even higher level layer on top of busboy called reformed. It comes with an Express middleware and can also be used separately.
Here is what i found googling around:
var fileupload = require("express-fileupload");
app.use(fileupload());
Which is pretty simple mechanism for uploads
app.post("/upload", function(req, res)
{
var file;
if(!req.files)
{
res.send("File was not found");
return;
}
file = req.files.FormFieldName; // here is the field name of the form
res.send("File Uploaded");
});
1) Make sure that your file is really sent from the client side. For example you can check it in Chrome Console:
screenshot
2) Here is the basic example of NodeJS backend:
const express = require('express');
const fileUpload = require('express-fileupload');
const app = express();
app.use(fileUpload()); // Don't forget this line!
app.post('/upload', function(req, res) {
console.log(req.files);
res.send('UPLOADED!!!');
});
It looks like body-parser did support uploading files in Express 3, but support was dropped for Express 4 when it no longer included Connect as a dependency
After looking through some of the modules in mscdex's answer, I found that express-busboy was a far better alternative and the closest thing to a drop-in replacement. The only differences I noticed were in the properties of the uploaded file.
console.log(req.files) using body-parser (Express 3) output an object that looked like this:
{ file:
{ fieldName: 'file',
originalFilename: '360px-Cute_Monkey_cropped.jpg',
name: '360px-Cute_Monkey_cropped.jpg'
path: 'uploads/6323-16v7rc.jpg',
type: 'image/jpeg',
headers:
{ 'content-disposition': 'form-data; name="file"; filename="360px-Cute_Monkey_cropped.jpg"',
'content-type': 'image/jpeg' },
ws:
WriteStream { /* ... */ },
size: 48614 } }
compared to console.log(req.files) using express-busboy (Express 4):
{ file:
{ field: 'file',
filename: '360px-Cute_Monkey_cropped.jpg',
file: 'uploads/9749a8b6-f9cc-40a9-86f1-337a46e16e44/file/360px-Cute_Monkey_cropped.jpg',
mimetype: 'image/jpeg',
encoding: '7bit',
truncated: false
uuid: '9749a8b6-f9cc-40a9-86f1-337a46e16e44' } }
multer is a middleware which handles “multipart/form-data” and magically & makes the uploaded files and form data available to us in request as request.files and request.body.
installing multer :- npm install multer --save
in .html file:-
<form method="post" enctype="multipart/form-data" action="/upload">
<input type="hidden" name="msgtype" value="2"/>
<input type="file" name="avatar" />
<input type="submit" value="Upload" />
</form>
in .js file:-
var express = require('express');
var multer = require('multer');
var app = express();
var server = require('http').createServer(app);
var port = process.env.PORT || 3000;
var upload = multer({ dest: 'uploads/' });
app.use(function (req, res, next) {
console.log(req.files); // JSON Object
next();
});
server.listen(port, function () {
console.log('Server successfully running at:-', port);
});
app.get('/', function(req, res) {
res.sendFile(__dirname + '/public/file-upload.html');
})
app.post('/upload', upload.single('avatar'), function(req, res) {
console.log(req.files); // JSON Object
});
Hope this helps!
Please use below code
app.use(fileUpload());
Just to add to answers above, you can streamline the use of express-fileupload to just a single route that needs it, instead of adding it to the every route.
let fileupload = require("express-fileupload");
...
//Make sure to call fileUpload to get the true handler
app.post("/upload", fileupload(), function(req, res){
...
});
A package installation needs for this functionality, There are many of them but I personally prefer "express-fileupload". just install this by "npm i express-fileupload" command in the terminal and then use this in your root file
const fileUpload = require("express-fileupload");
app.use(fileUpload());
PROBLEM SOLVED !!!!!!!
Turns out the storage function DID NOT run even once.
because i had to include app.use(upload) as upload = multer({storage}).single('file');
let storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './storage')
},
filename: function (req, file, cb) {
console.log(file) // this didn't print anything out so i assumed it was never excuted
cb(null, file.fieldname + '-' + Date.now())
}
});
const upload = multer({storage}).single('file');
I added multer as global middleware before methodOverride middleware,
and it worked in router.put as well.
const upload = multer({
storage: storage
}).single('featuredImage');
app.use(upload);
app.use(methodOverride(function (req, res) {
...
}));
With Formidable :
const formidable = require('formidable');
app.post('/api/upload', (req, res, next) => {
const form = formidable({ multiples: true });
form.parse(req, (err, fields, files) => {
if (err) {
next(err);
return;
}
res.json({ fields, files });
});
});
https://www.npmjs.com/package/formidable
You can use express-fileupload npm package to decode files like
const fileUpload = require('express-fileupload');
app.use(fileUpload({useTempFile: true}))
Note: I am using cloudinary to upload image
enter image description here
express-fileupload looks like the only middleware that still works these days.
With the same example, multer and connect-multiparty gives an undefined value of req.file or req.files, but express-fileupload works.
And there are a lot of questions and issues raised about the empty value of req.file/req.files.

Renaming Files with Node.js

I am new to node and trying to find a way to load some pdf files in an object from a directory. with an input and then rename the files based on the user input entered. I have 2 problems.
1 problem is the fs.readdirSync(directory); call is running on program start up. I need that call to be made when the page loads.
second problem is I am not finding how to take the value of the input and use the fs.rename to rename the files. Or create new files if necessary.
(this is going to be an internal app used locally only in a small office to rename pdf files for a specific purpose. Not a web app. Just wanted a simple UI for the staff.)
index.js
var express = require('express');
var app = express();
var path = require('path');
var formidable = require('formidable');
var ejs = require('ejs');
var fs = require('fs');
// set the view engine to ejs
app.set('view engine', 'ejs');
app.use(express.static(path.join(__dirname, 'public')));
app.use('/img', express.static(__dirname + '/img'));
//fs
let directory = "img";
let dirBuf = Buffer.from(directory);
// Buffer mydata
function bufferFile(relPath) {
return fs.readdirSync(path.join(__dirname, relPath));
console.log("hello from bufferFile"); // zzzz....
}
// let files = fs.readdirSync(directory);
// console.log(files, "This is the fs.readdirSync");
let files = fs.readdirSync(directory);
console.log(files, "This is the fs.readdirSync");
//routes
app.get('/', function(req, res){
res.sendFile(path.join(__dirname, 'views/index.html'));
});
//routes
app.get('/new', function(req, res){
// fs.readdir(specs, (err, files) => {
// files.forEach(file => {
// });
// })
res.render('rename',{
files: files,
});
});
app.get('/rename', function(req,res){
res.render('rename',{
files: files,
dirBuf: dirBuf
});
});
app.post('/upload', function(req, res){
// create an incoming form object
var form = new formidable.IncomingForm();
// specify that we want to allow the user to upload multiple files in a single request
form.multiples = true;
// store all uploads in the /uploads directory
form.uploadDir = path.join(__dirname, '/img');
// every time a file has been uploaded successfully,
// rename it to it's orignal name
form.on('file', function(field, file) {
fs.rename(file.path, path.join(form.uploadDir, file.name));
});
// log any errors that occur
form.on('error', function(err) {
console.log('An error has occured: \n' + err);
});
// once all the files have been uploaded, send a response to the client
form.on('end', function() {
res.end('success');
});
// parse the incoming request containing the form data
form.parse(req);
});
var server = app.listen(3000, function(){
console.log('Server listening on port 3000');
});
rename.ejs
<!-- views/partials/head.ejs -->
<% include ./partials/head %>
<ul>
<% files.forEach(function(files) { %>
<div class="col-lg-6">
<div class="form-group">
<h3><%= files %></h3>
<object data='img/<%= files %>' type='application/pdf' width='100%' height='250px'></object>
<input class="form-control" id="<%=files.name%>" value="<%=files.name%>">
</div>
</div>
<% }); %>
</ul>
<button type="submit" class="btn btn-primary">Submit</button>
<% include ./partials/footer%>
<!-- views/partials/footer.ejs -->

How to post form data in a nodejs application with routes?

I tried to build a simple node application with routes, but it gives a 404 network error as it's unable to post. Can someone please point out my mistake and correct it?
First I created a directory sampProj, then in it, I've a file - appl.js and a directory routes. Inside routes directory, I've a directory routes and a file main.js. Again inside mainCode directory, I've 3 files - main.js, server.js and index.html.
Sorry for the complicated directions, I wanted to test out small and then start building on it. I want to mention that this code with just server.js and index.html worked without the routes, i.e server.js uses app.post and app.get etc. instead of the corresponding router methods which I've shown below.
So here's the code for the application:
appl.js:
var express = require('express');
var bodyParser = require('body-parser');
var app = module.exports.app = express();
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false}));
// parse application/json
app.use(bodyParser.json());
// Adding routes
var server = require(__dirname + '/routes/main');
var mainCode = require(__dirname + '/routes/mainCode/main.js');
app.use('/Service', server);
app.use('/Service/mainCode', mainCode);
// Catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
/* Error Handlers */
// It will print the Stacktrace of error
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.send({
message: err.message,
error: err
});
});
}
app.listen(3000,function(){
console.log("Working on port 3000");
});
routes/main.js:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.send('<code>Welcome to Service</code>');
});
module.exports = router;
mainCode/main.js:
var express = require('express');
var router = express.Router();
var server = require(__dirname + '/server');
router.use('/server', server);
module.exports = router;
mainCode/index.html
<html>
<head>
<title>Form Data</title>
</head>
<body>
<form id="uploadForm" enctype="multipart/form-data" action="/" method="post">
<input id = "userPhotos" type="file" name="userPhotos" multiple />
<input type='text' id='random' name='random'><br>
<input type="submit" value="Upload" name="submit">
</form>
</body>
</html>
mainCode/server.js:
var express = require("express");
var router = express.Router();
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './uploads/');
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '-' + file.originalname);
}
});
var upload = multer({ storage : storage }).any();
router.get('/',function(req,res){
res.sendFile(__dirname + "/index.html");
});
router.post('/',function(req,res){
console.log("posted");
console.log("posted");
console.log(req.body);
upload(req,res,function(err) {
if(err) {
console.error(err);
return res.end("Error uploading file.");
}
console.log(req.body);
console.log(req.files);
res.end("File is uploaded");
});
});
module.exports = router;
Once I open localhost:3000/Service/mainCode/server in a browser, a form is displayed with one text input, but if I submit data, it's redirecting to localhost:3000 with error 404 displayed on the screen.
If you downvote this, please tell me why you're doing so, and in what way I can improve the question.
You access the form via the URL:
http://localhost:3000/Service/mainCode/server
right?
In your mainCode/server.js you set the get as well as the post handling for the same URL.
So why do you call the root directory in mainCode/index.html on form submit:
<form id="uploadForm" enctype="multipart/form-data" action="/" method="post">
it should be:
<form id="uploadForm" enctype="multipart/form-data" action="/Service/mainCode/server" method="post">
as far as I understand.
Usually if you want to send a formular to the same URL you would just leave the action attribute out like:
<form id="uploadForm" enctype="multipart/form-data" method="post">
EDIT: Turned out that it solved the problem for the OP combined with the removing of the attribute enctype, which leads to the default application/x-www-form-urlencoded method.
But as the OP wanted to submit a file in the first place, he had to exchange the body-parser module with multer and set the enctype to multipart/form-data again.
Documentation of multer:
https://github.com/expressjs/multer

Retrieve the image path of the file uploaded

I have written a code that will allow the user to upload an image to the server. My code is as follows:
My backend is in Node JS. What I want is to retrieve the file path of the image file so i can upload it. This is to be done from the Node JS side.
The code I have written doesn't work. It crashes while retrieving the path of the image file.
<div class="form-group">
<input id="input-700" name="kartik-input-700[]" type="file" multiple class="file-loading" name="fileupload">
</div>
JAVASCRIPT
<script type="text/javascript">
$(document).ready(function(){
$("#input-700").fileinput({
uploadUrl: "/filllll/uploadIm", // server upload action
allowedFileExtensions: ['jpg', 'png'],
uploadAsync: true,
maxFileCount: 1
});
var fullPath = $("#input-700").val();
alert(fullPath);
});
</script>
Node JS
router.post('/uploadIm', function (req, res, next) {
console.log('IThe path of the file' + res.fieldname);
});
Express does not this out of the box. You need to handle multipart/form-data. The easiest way to do this - to use the middleware. For example, multer:
var express = require('express')
var multer = require('multer')
var upload = multer({ dest: 'uploads/' })
var app = express()
app.post('/profile', upload.single('avatar'), function (req, res, next) {
// req.file is the `avatar` file
// req.body will hold the text fields, if there were any
})

Categories

Resources