I want to upload img using node.js , i am using express and multiparty , my code looks like
html
<!DOCTYPE html>
<html>
<body>
<form method="post" action="/img">
Select image to upload:
<input type="file" name="fileToUpload" id="fileToUpload">
<input type="submit" value="Upload Image" name="submit">
</form>
</body>
</html>
js
var express = require("express");
var app=express();
var http=require("http").Server(app);
app.get("/",function(req,res){
res.end("hello")
});
app.get("/upload",function(req,res){
res.sendFile(__dirname + "/form.html")
})
app.post("/img",function(req,res){
var multiparty = require("multiparty");
var form = new multiparty.Form();
form.parse(req,function(err,fields,files){
var img = files.images[0];
console.log(img)
})
})
http.listen(3000,function(){
console.log("listening on 3000")
})
When i upload something , it throws error
Cannot read property images of undefined
Being new to back end i have no idea why its happening , the directory img exists in folder where html and js are located.
Add enctype to form:
<form method="post" action="/img" enctype="multipart/form-data">
PS: For upload image, I suggest you use formidable, somelike this.
you can use multer for uploading files, see the code below, For front end:
<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 :
var express = require("express");
var multer = require("multer");
var bodyParser = require("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',1);
app.get('/',function(req,res){
res.sendFile(__dirname + "/fileUpload.html");
});
app.post('/api/photo',function(req,res){
upload(req,res,function(err) {
if(err) {
return res.end("Error uploading file.");
}
res.end("File is uploaded");
});
});
app.listen(3000,function(){
console.log("Working on port 3000");
});
and you can upload multiple files at same time if you want, for example increase the userPhoto to 5 var upload = multer({ storage : storage }).array('userPhoto',5);
Related
I made a simple nodejs server which serves a html page to the user.The page contains a input text box of userID. When the user presses the button submit, I take that userID entered by the user and put it in form Data and send it to my server function (submitForTest) through POST method.
Now, inside my function of nodejs which handles submitForTest, I tried to access the userID , but I was getting res.body as {} , so not able to figure out how to access userID here.
Can anyone please point what I need to get the userID at my node js code.
My HTML file :
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div>
<label>User ID</label>
<div>
<input type="text" id="userid" >
</div>
</div>
<div>
<div>
<button type="submit" onclick="submitForTest()">Submit</button>
</div>
</div>
<script type="text/javascript">
function submitForTest()
{
var userID = document.getElementById('userid').value;
let formData = new FormData();
formData.append("userID", userID);
//alert("hello");
fetch('http://MY-SERVER:3000/submitForTest', {method: "POST", body: formData});
}
</script>
</body>
</html>
My Node js file :
'use strict'
const fs = require("fs")
const express = require('express')
var path = require('path')
const app = express()
var bodyParser = require('body-parser')
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
var jsonParser = bodyParser.json();
app.get('/',function(req,res) {
res.sendFile('small.html');
});
app.post('/submitForTest', function(req, res) {
//want to print userID here .. but the below is coming as {} here ..
console.log(req.body);
})
// Tell our app to listen on port 3000
app.listen(3000, function (err) {
if (err) {
throw err;
}
console.log('Server started on port 3000')
})
Please help.
Regards
The problem is FormData is sending body encoded as multipart/form-data. You'll have to add middleware able to handle multipart body format. Busboy or multer for example.
Example of using multer to upload a file and send userID field:
// --- form
<form action="/submitForTest" enctype="multipart/form-data" method="post">
<input type="file" name="uploaded_file">
<input type="text" name="userID">
<input type="submit" value="Submit">
</form>
// --- server
var multer = require('multer')
var upload = multer({ dest: './uploads/' }) // where the uploaded files will be stored
app.post('/submitForTest', upload.single('uploaded_file'), function (req, res) {
// req.file is the name of your file in the form above, here 'uploaded_file'
// req.body will hold the text fields, if there were any
console.log(req.file, req.body)
});
Or to send your data in urlencoded or json format. Something like that for json for example:
function submitForTest()
{
var userID = document.getElementById('userid').value;
fetch('http://MY-SERVER:3000/submitForTest', {
method: "POST",
headers: {
'Content-type': 'application/json',
},
body: JSON.stringify({ userID }),
});
}
html:
<form method='post' action='upload_bg' enctype="multipart/form-data">
<input type='file' name='fileUploaded'>
<input type='submit'>
My index.js
app.route('/upload_bg')
.post(function (req, res) {
var fstream;
req.busboy.on('file', function (fieldname, file, filename) {
console.log(filename);
fstream = fs.createWriteStream(__dirname + '/imgs/' + "latest_upload.jpg");
file.pipe(fstream);
fstream.on('close', function () {
res.redirect('back');
});
});
});
My variables:
var express = require('express');
var busboy = require('connect-busboy');
var path = require('path');
var fs = require('fs-extra');
So the user clicks the button, selects an image, and selects submit. This hit's my route upload_bg. I've had it working before, and I changed a few things around but I'm unable to understand why it isn't working. I look in the network tab and the request is just pending indefinitely.
Here is my simple solution using express-fileupload module:
First intall express fileupload module using following command:
npm install express-fileupload
HTML page code:
<html>
<body>
<form ref='uploadForm'
id='uploadForm'
action='http://localhost:3000/upload_bg'
method='post'
encType="multipart/form-data">
<input type="file" name="sampleFile" />
<input type='submit' value='Upload!' />
</form>
</body>
</html>
node server code:
server.js:
var express=require('express');
var app = express();
var fileUpload = require('express-fileupload');
// default options
app.use(fileUpload());
app.post('/upload_bg', function(req, res) {
if (!req.files)
return res.status(400).send('No files were uploaded.');
// The name of the input field (i.e. "sampleFile") is used to retrieve the uploaded file
let sampleFile = req.files.sampleFile;
// Use the mv() method to place the file somewhere on your server
// Make sure 'imgs' folder is already created inside current directory otherwise it will throw error where this server.js file is placed
sampleFile.mv(__dirname + '/imgs/latest_upload.jpg', function(err) {
if (err)
return res.status(500).send(err);
res.send('File uploaded!');
});
});
app.listen(3000,function(){
console.log("App listening on port 3000")
});
Hope this will help. For complete code refer https://github.com/richardgirges/express-fileupload
I would personally re-style your code a little bit. And I would use ajax. Here is some example code:
index html:
<button class="btn btn-lg upload-btn" type="button">Upload image</button>
<input id="upload-input" type="file" name="uploads[]" multiple="multiple">
client js:
This can/should be inside of index.html
$('.upload-btn').on('click', function (){
$('#upload-input').click();
$('.progress-bar').text('0%');
$('.progress-bar').width('0%');
});
$('#upload-input').on('change', function(){
var files = $(this).get(0).files;
if (files.length > 0){
// create a FormData object which will be sent as the data payload in the
// AJAX request
var formData = new FormData();
// loop through all the selected files and add them to the formData object
for (var i = 0; i < files.length; i++) {
var file = files[i];
// add the files to formData object for the data payload
formData.append('uploads[]', file, file.name);
}
$.ajax({
url: '/upload',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(data){
console.log('upload successful!\n' + data);
},
});
}
});
server js:
var express = require('express');
var app = express();
var path = require('path');
var formidable = require('formidable');
var fs = require('fs');
var l;
//... other code here
app.get('/upload', function(req, res){
res.sendFile(path.join(__dirname, 'index.html'));
});
app.post('/upload', function(req, res){
var form = new formidable.IncomingForm();
form.multiples = true;
form.uploadDir = path.join(__dirname, '/uploads');
form.on('file', function(field, file) {
fs.readdir('uploads/', function(err, items) {
console.log(items.length);
l = items.length
console.log(l);
fs.rename(file.path, "uploads/"+l+".jpg", function(err) {
if ( err ) console.log('ERROR: ' + err);
});
});
});
form.on('error', function(err) {
console.log('An error has occured: \n' + err);
});
form.on('end', function() {
res.end('success');
});
form.parse(req);
});
Hope this helps!
Client side:
I have done file upload with AngularJS and NodeJS it's working but while uploading file i need to pass 'name' and 'email' to server.
Server side:
After uploading file into folder i need to save file path, name and email into database. How can i do this?
angular.module('fileUpload', ['ngFileUpload'])
.controller('MyCtrl',['Upload','$window',function(Upload,$window){
var vm = this;
vm.submit = function(){ //function to call on form submit
if (vm.upload_form.file.$valid && vm.file) { //check if from is valid
vm.upload(vm.file); //call upload function
}
}
vm.upload = function (file) {
console.log(vm.name);
console.log(vm.email);
Upload.upload({
url: 'http://localhost:3000/upload', //webAPI exposed to upload the file
data:{file:file} //pass file as data, should be user ng-model
}).then(function (resp) { //upload function returns a promise
if(resp.data.error_code === 0){ //validate success
$window.alert('Success ' + resp.config.data.file.name + 'uploaded. Response: ');
} else {
$window.alert('an error occured');
}
}, function (resp) { //catch error
console.log('Error status: ' + resp.status);
$window.alert('Error status: ' + resp.status);
}, function (evt) {
console.log(evt);
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
console.log('progress: ' + progressPercentage + '% ' + evt.config.data.file.name);
vm.progress = 'progress: ' + progressPercentage + '% '; // capture upload progress
});
};
}]);
<script src="http://cdn.bootcss.com/danialfarid-angular-file-upload/12.2.13/ng-file-upload-shim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-file-upload/2.4.1/angular-file-upload.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<html>
<head>
<title>Home</title>
</head>
<body ng-app="fileUpload">
<h1>Angular Node File Upload</h1>
<form ng-controller="MyCtrl as up" name="up.upload_form">
name
<input type="text" ng-model="up.name"><br> <br>
email
<input type="text" ng-model="up.email"><br>
Image
<input
type="file"
ngf-select
ng-model="up.file"
name="file"
ngf-max-size="20MB"
/>
Image thumbnail: <img style="width:100px;" ng-show="!!up.file" ngf-thumbnail="up.file || '/thumb.jpg'"/>
<i ng-show="up.upload_form.file.$error.required">*required</i><br>
<i ng-show="up.upload_form.file.$error.maxSize">File too large
{{up.file.size / 1000000|number:1}}MB: max 20M</i>
<!-- Multiple files
<div class="button" ngf-select ng-model="up.files" ngf-multiple="true">Select</div>
Drop files: <div ngf-drop ng-model="up.files" class="drop-box">Drop</div> --><br>
<button type="submit" ng-click="up.submit()">submit</button>
<p>{{up.progress}}</p>
</form>
</body>
</html>
Backend code:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var multer = require('multer');
app.use(function(req, res, next) { //allow cross origin requests
res.setHeader("Access-Control-Allow-Methods", "POST, PUT, OPTIONS, DELETE, GET");
res.header("Access-Control-Allow-Origin", "http://localhost");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
/** Serving from the same express Server
No cors required */
app.use(express.static('../client'));
app.use(bodyParser.json());
var storage = multer.diskStorage({ //multers disk storage settings
destination: function (req, file, cb) {
cb(null, './uploads/');
},
filename: function (req, file, cb) {
var datetimestamp = Date.now();
cb(null, file.fieldname + '-' + datetimestamp + '.' + file.originalname.split('.')[file.originalname.split('.').length -1]);
}
});
var upload = multer({ //multer settings
storage: storage
}).single('file');
/** API path that will upload the files */
app.post('/upload', function(req, res) {
console.log(req.body);
upload(req,res,function(err){
if(err){
res.json({error_code:1,err_desc:err});
return;
}
res.json({error_code:0,err_desc:null});
});
});
app.listen('3000', function(){
console.log('running on 3000...');
});
i tried like this
Upload.upload({
url: 'http://localhost:3000/upload', //webAPI exposed to upload the file
data:{file:file, name:vm.name, email:vm.email} //pass file as data, should be user ng-model
})
backend
app.post('/upload', function(req, res) {
console.log(req.body);
console.log(req.file);
upload(req,res,function(err){
if(err){
res.json({error_code:1,err_desc:err});
return;
}
res.json({error_code:0,err_desc:null});
});
});
in front end(angular)i am getting value what ever i entered in form but backend(nodejs) i am getting undefined value
You need to amend your angular code to send the extra info in the data of the request
Upload.upload({
url: 'http://localhost:3000/upload', //webAPI exposed to upload the file
data:{file:file, name:vm.name, email:vm.email} //pass file as data, should be user ng-model
})
Then in your backend code you can reference this on the body of the request
req.body.name
req.body.email
I not sure if my answer will help you. But you can add in your data the name and the email.
Upload.upload({
url: 'http://localhost:3000/upload', //webAPI exposed to upload the file
data:{file:file,name:"putHeretheName",email:"putHereTheMail"} //pass file as data, should be user ng-model
}
Then server side you can create a function or complete your actual "/upload" with a query that save in your bdd what you want. You just have to get the name of the path created and then do the save in case of your upload is successful.
Maybe this e.g will help you more: https://www.npmjs.com/package/ng-file-upload
You can add a file property that will hold the file and update the data property to contain email and name inside the Upload.upload object. This way you can get them easily at the server side.
Note: I have updated my answer, I wrapped all the values Angular viewis emitting inside a params object. I also changed angular-ng-upload CDN wasn't working on codepen. You should also load Angular.js first.
view
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://angular-file-upload.appspot.com/js/ng-file-upload-shim.js"></script>
<script src="https://angular-file-upload.appspot.com/js/ng-file-upload.js"></script>
<html>
<head>
<title>Home</title>
</head>
<body ng-app="fileUpload">
<h1>Angular Node File Upload</h1>
<form ng-controller="MyCtrl as up" name="up.upload_form">
name
<input type="text" ng-model="up.params.name"><br> <br>
email
<input type="text" ng-model="up.params.email"><br>
Image
<input
type="file"
ngf-select
ng-model="up.params.file"
name="file"
ngf-max-size="20MB"
/>
Image thumbnail: <img style="width:100px;" ng-show="!!up.params.file" ngf-thumbnail="up.params.file || '/thumb.jpg'"/>
<i ng-show="up.upload_form.params.file.$error.required">*required</i><br>
<i ng-show="up.upload_form.params.file.$error.maxSize">File too large
{{up.params.file.size / 1000000|number:1}}MB: max 20M</i>
<!-- Multiple files
<div class="button" ngf-select ng-model="up.files" ngf-multiple="true">Select</div>
Drop files: <div ngf-drop ng-model="up.files" class="drop-box">Drop</div> --><br>
<button type="submit" ng-click="up.submit()">submit</button>
<p>{{up.progress}}</p>
<p>{{up.params}}{{up.params.file.size}}</p>
</form>
</body>
</html>
Angular
var vm = this;
vm.submit = function(){
if (vm.upload_form.file.$valid && vm.params.file) {
console.log(vm.params)
vm.upload(vm.params); // Pass the `vm.params` object.
}
}
vm.upload = function (params) {
console.log(params.name); // params.name should be available
console.log(params.email); // params.email should be available
console.log(params.file); // params.file should be available
Upload.upload({
url: 'http://localhost:3000/upload',
file: params.file, // Image to upload
data: {
name: params.name,
email: params.email
}
})
}
Node.js/express
app.post('/upload', function(req, res) {
console.log(JSON.parse(req.body.data)); // email and name here
console.log(req.files.file); // file object
upload(req,res,function(err){
if(err){
res.json({error_code:1,err_desc:err});
return;
}
res.json({error_code:0,err_desc:null});
});
});
I'm trying to upload a file in node js using multipart where I get Cannot POST error? I'm totally new to node js. So can you help me what I'm doing wrong
My Code?
HTML
<form id = "uploadForm"
enctype = "multipart/form-data"
action = "/api/uploadfile"
method = "post">
<input type="file" name="fileUpload"/>
<input type="submit" value="Upload File" name="submit">
</form>
Server.js
var express = require('express');
var app = express();
var multer = require('multer');
app.use(express.static(__dirname));
app.get('/', function(request, response){
response.sendFile("./index.html");
});
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}).single('fileUpload');
app.post('/api/uploadfile',function(req,res){
upload(req,res,function(err) {
if(err) {
return res.end("Error uploading file.");
}
res.end("File is uploaded");
});
});
app.listen(8080);
console.log("App listening on port 8080");
Error message as follows :
Error uploading file
i tried your code,its working here.The reason may be,
1)you missed out the closing of form tag
<html>
<form id = "uploadForm"
enctype = "multipart/form-data"
action = "/api/uploadfile"
method = "post"
>
<input type="file" name="fileupload" />
<input type="submit" value="Upload file" name="submit">
</form>
</html>
2)make sure that you have a folder named -> uploads
I have this code in order to upload files with node.js:
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());
app.get('/',function(req,res){
fs.readFile('uploadHTML.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");
});
});
});
Here is the 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>
When I upload the file, it gives me the next error:
TypeError: Cannot read property 'displayImage' of undefined at c:\NodeInstall\nodejs\express.js:42:22 at callbacks (c:\NodeInstall\nodejs\node_modules\express\lib\router\index.js:164:37) at param (c:\NodeInstall\nodejs\node_modules\express\lib\router\index.js:138:11) at pass (c:\NodeInstall\nodejs\node_modules\express\lib\router\index.js:145:5) at Router._dispatch (c:\NodeInstall\nodejs\node_modules\express\lib\router\index.js:173:5) at Object.router (c:\NodeInstall\nodejs\node_modules\express\lib\router\index.js:33:10) at next (c:\NodeInstall\nodejs\node_modules\express\node_modules\connect\lib\proto.js:193:15) at Object.expressInit [as handle] (c:\NodeInstall\nodejs\node_modules\express\lib\middleware.js:30:5) at next (c:\NodeInstall\nodejs\node_modules\express\node_modules\connect\lib\proto.js:193:15) at Object.query [as handle] (c:\NodeInstall\nodejs\node_modules\express\node_modules\connect\lib\middleware\query.js:45:5)
What could be the reason?
I do recommend you to use awesome module https://github.com/domharrington/fileupload for handling file uploads in node/express.
var fileupload = require('fileupload').createFileUpload('/uploadDir').middleware
app.post('/upload', fileupload, function(req, res) {
// files are now in the req.body object along with other form fields
// files also get moved to the uploadDir specified
})
Another way to upload files could be using something like this
Jade template
form.data(action='/user/register', method='post', class="long-fields", enctype='multipart/form-data')
input(type="text" name="name")
input(name='fileLogo', type='file')
input(type="submit" value="Register")
Controller
formidable = require('formidable'); //file upload handling via form
uuid = require('node-uuid'); //Unique ID
path = require('path'); //Path compiler
fs = require('fs'); //FileSystem
var form = new formidable.IncomingForm();
form.keepExtensions = false;
form.maxFieldsSize = 2 * 1024 * 1024; //2mb
form.parse(req, function(err, fields, files) {
console.log(fields);
console.log(files);
fs.readFile(files.fileLogo.path, function (err, data) {
var pathNew = __dirname + '/../../uploads/' + uuid.v1() + path.extname(files.fileLogo.name)
fs.writeFile(pathNew, data, function (err) {
console.log('uploaded', pathNew);
});
});
res.send(jade.renderFile( settings.pathLess + prefix + '/register.jade', {
req : req
}));
});