File upload in node.js - node.js

I want to upload my file in my workspace and read it in node.js.
Html code:
<html>
<head>
<script src = "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
</head>
<body>
<div ng-app="" ng-controller="SalesImportControl">
<form ng-submit="readCustomer()">
<input type="file" name="file" file-model = "myFile">
<br>
<button type="submit" >Submit</button>
</form>
</div>
</body>
</html>
Controller:
'use strict';
angular.module('app')
.controller('SalesImportControl', ['$scope','$http', '$location', '$rootScope','fileUpload' , function($scope, $http, $location, $rootScope,fileUpload) {
console.log(" In dataimportCtrl");
//customer
$scope.readCustomer = function(req,res){
var file1=$scope.myFile;
var fl1 = $scope.myFile.name;
console.log("file name:"+$scope.myFile.name);
var uploadUrl = "/fileUpload";
var fd = new FormData();
fd.append('file', file1);
//File upload
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).success(function(data){
}).error(function(){
});
//sales
$http.post('/salesimport', { params: fl1 }).success(function(data) {
console.log("in controller1");
console.log("controller:"+data);
$scope.data=data["jarr"];
$scope.data1=data["jarr1"];
$scope.data2=data["jarr2"];
$scope.data3=data["jarr3"];
$scope.data4=data["jarr4"];
}).error(function(response) {
console.error("error in posting");
});
};
}])
Server.js:
var express = require('express');
var bodyparser = require('body-parser');
var mysql = require('mysql');
var app = express();
var formidable = require('formidable');
var path = require('path');
var fs = require('fs');
var _ = require('underscore');
var vouchersmodel = require('./models/v_db.js');
app.use(express.static(__dirname + "/public/angular"));
app.use(bodyparser.json());
app.listen(3000);
console.log('Server running on 3000');
app.post('/fileUpload', function (req, res) {
var form = new formidable.IncomingForm();
//Formidable uploads to operating systems tmp dir by default
form.uploadDir = __dirname+"/models/upload2/"; //set upload directory
form.keepExtensions = true; //keep file extension
form.parse(req, function(err, fields, files) {
res.writeHead(200, {'content-type': 'text/xml'});
res.write('received upload:\n\n');
console.log("form.bytesReceived");
console.log("file size: "+JSON.stringify(files.file.size));
console.log("file path: "+JSON.stringify(files.file.path));
console.log("file name: "+JSON.stringify(files.file.name));
console.log("file type: "+JSON.stringify(files.file.type));
console.log("astModifiedDate:"+JSON.stringify(files.file.lastModifiedDate));
console.log("file:"+JSON.stringify(files.file));
vouchersmodel.upload(files.file.path,files.file.name, function (msg) {
return res.json(msg);
});
});
});
Model:
exports.upload= function(r,name,callback){
var fs = require('fs');
var newPath = __dirname + "/upload2/"+name;
fs.readFile(r, function (err, data) {
fs.writeFile(newPath,data, function (err,res) {
if(!err){
console.log("uploaded.........");
callback();
}
});
});
}
My question is it uploads the file but before uploading the file it runs the salesimport post method in controller and shows no such directory error.
Where I am wrong ?
Note:
salesimport post method request accesses the file uploaded in model.

Related

Nodejs TypeError: Busboy is not a constructor

I am working through some tutorials to build a chat server with file upload. I have no prior experience with NodeJS I have been following along with the instructor's code, but recently hit a snag that I cannot resolve. When trying to build the project to run test scripts via npm run dev, I get the following error. it want to recive that the file is uploaded into the uploads folder in my project :
Console log code:
TypeError: Busboy is not a constructor
at C:\Users\xxx\Desktop\chat\server.js:24:20
in chrome Dev tools
Failed to load resource: the server responded with a status of 500 (Internal Server Error)
answers i found online seems that i have to change the code and i have to call this instead:
const busboyCons = require('busboy');
...
var busboy = busboyCons({ headers: req.headers });
source: https://gist.github.com/shobhitg/5b367f01b6daf46a0287
i also runned this but it dont worked for me. Any help resolving this error would be greatly appreciated -- I'm kind of stuck with it.
server.js:
const express= require('express');
const app= express();
const path = require('path');
const http= require('http').createServer(app);
const PORT=process.env.PORT || 3000;
const io=require('socket.io')(http);
const fs = require('fs');
const Busboy = require('busboy');
app.use(express.static(__dirname + '/public'))
app.use(express.static('uploads'))
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
app.get('/css/main.css', function(req, res) {
res.sendFile(__dirname + "/public" + "/style.css");
});
app.post('/upload', function(req, res) {
const busboy = new Busboy({ headers: req.headers });
req.pipe(busboy);
busboy.on('file', ( fieldname, file, filename) => {
const ext = path.extname(filename);
const newFilename = `${Date.now()}${ext}`;
req.newFilename = newFilename;
req.originalFilename = filename;
const saveTo = path.join('uploads', newFilename);
file.pipe(fs.createWriteStream(saveTo));
});
busboy.on('finish', () => {
res.json({
originalFilename: req.originalFilename,
newFilename: req.newFilename
});
});
});
io.on('file', f => {
console.log(`File by: ${f.userName}`);
socket.emit('file', f);
});
client.js:
const socket = io()
let textarea=document.querySelector('#textarea')
let messageArea= document.querySelector('.message_area')
let formAreaFileUpload=document.querySelector('.submitMediaFiles')
let formSubmit=document.querySelector('#form')
// preventDefault();
formSubmit.addEventListener("submit",handleFormSubmit)
function handleFormSubmit(e) {
e.preventDefault();
console.log(e)
const form = $(this);
const formData = new FormData(form[0])
for (const p of formData) {
if (p[1].size <= 0) {
return
}
}
$.ajax({
method: 'POST',
data: formData,
cache: false,
contentType: false,
processData: false,
url: '/upload',
success: handleUploadSuccess,
})
}
function handleUploadSuccess(resp) {
socket.emit('file', { userName, file: { url: `/${resp.newFilename}`, filename: resp.originalFilename } });
}
index.html (cutout):
<form id="form" style="background-color: #999999">
<div class="contentLine">
<div class="column">
<input id="data" type="file" name="file" />
</div>
<div class="column last">
<button style="float:right" type="submit">Send Multimediafile </button>
</div>
</div>
</form>
</section>
<script src="/socket.io/socket.io.js"></script>
<script src="/client.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
According to the documentation you should use busboy in this way:
const busboy = require('busboy');
const bb = busboy({ headers: req.headers });
But you said you tried and it didn't work. What error occurred then?
You can try lowering the version to 0.3.1, npm i busboy#0.3.1. I just lowered the version.

Getting TypeError: Cannot read property 'content-length' of undefined When Using Node.js Formidable

I'm trying to console.log a number I type in an input using formidable. I am getting an error that says TypeError: Cannot read property 'content-length' of undefined. I have tried to add a fs.readFile into the code and it won't work.
Here is my app.js
const express = require('express');
const http = require('http');
const formidable = require('formidable');
const fs = require('fs');
const ejs = require('ejs');
const path = require('path');
const multer = require('multer');
const upload = multer({ dest: 'upload/'});
const type = upload.fields([{ name: 'gradeNumber', maxCount: 10 }]);
const app = express();
app.use(express.static(__dirname + '/public'));
app.set('view engine', 'ejs');
app.get('/fileupload', function (req, res) {
res.render("upload")
});
app.post('/fileupload', function (req, res) {
const form = new formidable.IncomingForm();
form.parse(function (err, fields, files) {
console.log(fields.gradeNumber);
const oldpath = files.filetoupload.path;
const newpath = 'C:/Users/Shubh Computer/Desktop/VSCode/Grades/1/' + files.filetoupload.name;
fs.rename(oldpath, newpath, function (err) {
if (err) throw err;
res.write('File uploaded and moved!');
res.end();
});
});
});
app.listen(3000);
upload.ejs
<!DOCTYPE html>
<html>
<head>
<title>Upload File</title>
</head>
<body>
<form action="fileupload" method="post" enctype="multipart/form-data">
<input type="file" name="filetoupload"><br>
<label>What Grade</label><input type="text" name="gradeNumber"><br>
<input type="submit">
</form>
</body>
</html>
I'm trying to log the input with the name "gradeNumber". If somebody could help me I will be very grateful because I've gotten very frustrated with this.
"req" parameter in form.parse() method is omitted.
(method) IncomingForm.parse(req: IncomingMessage, callback?: (err: any, fields: Fields, files: Files) => any): void
Try changing the code as below.
app.post('/fileupload', function (req, res) {
const form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
console.log(fields.gradeNumber);
const oldpath = files.filetoupload.path;
const newpath = 'C:/Users/Shubh Computer/Desktop/VSCode/Grades/1/' + files.filetoupload.name;
fs.rename(oldpath, newpath, function (err) {
if (err) throw err;
res.write('File uploaded and moved!');
res.end();
});
});
});

NodeJS & express file upload with XMLHttpRequest - not working

I am uploading a file using this form and by the time xhr submits it the server does not recognize req.xhr === true, as such I can not process the file upload. What am I missing?
<form encType="multipart/form-data" method="post">
<Button onClick={(event)=>startUploadFile(event)} type="button">Upload</Button>
<input type="file" name="file" id="file" multiple="multiple" onChange={onChangeHandler} />
</form>
Client side
const [upFile, setUpFile] = useState('')
const onChangeHandler = event => {
setUpFile(event.target.files[0]);
}
const startUploadFile = e => {
setSpin('visible')
setMsg(`Uploading Media ...`)
e.preventDefault()
const data = new FormData()
data.append('file', upFile)
var formData = new FormData();
var xhr = new XMLHttpRequest();
var onProgress = function(e) {
if (e.lengthComputable) {
var percentComplete = (e.loaded/e.total)*100;
console.log('percentage = ' + percentComplete)
}
};
formData.append('files', upFile); // this is a state object set onChange
xhr.open('post', '/upload', true);
xhr.addEventListener('error', onError, false);
xhr.addEventListener('progress', onProgress, false);
xhr.send(formData);
xhr.addEventListener('readystatechange', onReady, false);
}
Server side
const express = require('express'),
app = express.Router(),
cors = require('cors'),
fs = require('fs-extra');
app.use(cors())
app.post('/uploadFile', (req, res) => {
if (req.xhr || req.headers.accept.indexOf('json') > -1) {
// not accepted (req.xhr is false always) why?
}
});
In expressjs you need to install multer or formidable package to upload file from client side application then you will receive your file in req.files object.
Thanks to #Nikas for the remarks - here is working solution if anyone needs it or something like it.
For the client side:
const startUploadFile = e => {
setSpin('visible')
setMsg(`Uploading Media ...`)
e.preventDefault()
const data = new FormData()
data.append('file', upFile)
var formData = new FormData();
var xhr = new XMLHttpRequest();
var onProgress = function(e) {
if (e.lengthComputable) {
var percentComplete = (e.loaded/e.total)*100;
console.log('% uploaded:' + percentComplete)
}
};
var onReady = function(e) {
console.log('ready')
};
var onError = function(err) {
console.log('something went wrong with upload');
};
formData.append('files', upFile); // this is a state object set onChange
xhr.open('post', '/media/uploadFile', true);
xhr.addEventListener('error', onError, false);
xhr.addEventListener('progress', onProgress, false);
xhr.send(formData);
xhr.addEventListener('readystatechange', onReady, false);
}
server side:
const express = require('express'),
app = express.Router(),
cors = require('cors'),
fs = require('fs-extra'),
formidable = require('formidable');
app.post('/uploadFile', (req, res) => {
const path = './client/public/upload/';
var form = new formidable.IncomingForm();
form.uploadDir = path;
form.encoding = 'binary';
form.parse(req, function(err, fields, files) {
if (err) {
console.log(err);
res.send('upload failed')
} else {
var oldpath = files.files.path;
var newpath = path + files.files.name;
fs.rename(oldpath, newpath, function (err) {
if (err) throw err;
res.send('complete').end();
});
}
});
})

Upload file to Local directory as well as MongoDB

I am having an issue in uploading the file to pc as well as DB at same time.
I am using two different Modules in my code
Multer: For uploading file from front-end to PC
CSV-to-JSON: For converting CSV File to json in order to store that file in Database.
But, using two separate functions isn't my intention at all.
So, when I tried combining both modules along with the base code, File uploading with Multer works but I want to upload that file to MongoDB which need to be solved by csv-to-json is a problem for me nothing seem's to be working.
here's is my code :
var express = require('express');
var multer = require('multer');
const csv = require('csvtojson');
// Import Mongodb
const mongoClient = require('mongodb').MongoClient,
assert = require('assert');
var filename = null;
var storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, 'uploads/')
},
filename: function(req, file, cb) {
filename = Date.now() + '-' + file.originalname;
cb(null, filename)
console.log(filename);
}
})
var upload = multer({
storage: storage
})
var app = express();
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
app.post('/', upload.single('file-to-upload'), function(req, res, next) {
// Mongodb Connection URL
const url = 'mongodb://localhost:27017/csvfilereader';
// Use connect method to connect to the Server
mongoClient.connect(url, (err, db) => {
assert.equal(null, err);
if (db) {
console.log("Connected correctly to server");
insertDocuments(db, function() {
db.close();
});
} else {
console.log('\n', 'Problem with connection', err)
}
});
const insertDocuments = (db, callback) => {
// Get the documents collection
let collection = db.collection('uploaded');
// CSV File Path
const csvFilePath = 'uploads/' + filename;
console.log(csvFilePath);
/**
* Read csv file and save every row of
* data on mongodb database
*/
csv()
.fromFile(csvFilePath)
.on('json', (jsonObj) => {
collection.insert(jsonObj, (err, result) => {
if (err) {
console.log(err);
} else {
console.log('suceess');
res.redirect('/');
filename = null;
}
});
})
.on('done', (error) => {
console.log('end')
})
}
});
app.listen(3200);
<!--
HTML Code that runs on Root
-->
<html lang="en">
<head>
<title>Simple Multer Upload Example</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<form action="/" enctype="multipart/form-data" method="post">
<input type="file" name="file-to-upload">
<input type="submit" value="Upload">
</form>
</body>
</html>
You need to access the file name through the passed request from multer. Your filename variable doesn't point to any object.
req.file.filename will give access to your file that has been uploaded by multer.
UPDATED CODE:
var express = require("express");
var multer = require("multer");
const csv = require("csvtojson");
// Import Mongodb
const MongoClient = require("mongodb").MongoClient,
assert = require("assert");
var filename = null;
var storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, "uploads/");
},
filename: function(req, file, cb) {
filename = Date.now() + "-" + file.originalname;
cb(null, filename);
},
});
var upload = multer({
storage: storage,
});
var app = express();
app.get("/", (req, res) => {
res.sendFile(__dirname + "/index.html");
});
app.post("/", upload.single("file-to-upload"), function(req, res, next) {
// Connection URL
const url = "mongodb://localhost:27017";
console.log("Multer", req.file.filename);
// Database Name
const dbName = "csvreader";
// Create a new MongoClient
const client = new MongoClient(url, { useNewUrlParser: true });
// Use connect method to connect to the Server
client.connect(function(err) {
assert.equal(null, err);
console.log("Connected successfully to database");
const db = client.db(dbName);
insertDocuments(db, function() {
console.log("Closing connection");
client.close();
});
});
const insertDocuments = (db, callback) => {
// Get the documents collection
const collection = db.collection("uploaded");
// CSV File Path
const csvFilePath = "uploads/" + filename;
console.log("Reading file from ", csvFilePath);
/**
* Read csv file and save every row of
* data on mongodb database
*/
csv()
.fromFile(csvFilePath)
.then(jsonObj => {
console.log(jsonObj);
collection.insert(jsonObj, (err, result) => {
if (err) {
console.log(err);
} else {
console.log("suceess");
res.redirect("/");
filename = null;
callback();
}
});
})
.catch(err => {
//error reading file
console.log(err);
});
};
});
app.listen(3200, () => {
console.log("Server working at port 3200");
});

file uploading not working in nodejs

I am trying to upload a file in nodejs using express and multer.
index.js
var mysql=require('mysql');
var session = require('express-session');
var multer=require('multer');
var express=require('express');
var path=require('path');
var cors=require('cors');
var nodemailer=require('nodemailer');
var fileupload=require('express-fileupload');
var fs=require('fs');
const app=express();
app.use(cors());
app.use(fileupload());
var bodyParser=require('body-parser');
app.use(bodyParser.json({limit: '5mb'}));
app.use(bodyParser.urlencoded({limit: '5mb',extended:true}));
require('./routes.js')(app,mc,fs,multer);
app.listen(8080,function() {
console.log('port listening on 8080');
})
routes.js
module.exports=function(app,mc,fs,multer) {
var storages = multer.diskStorage({
destination: function(req, file, callback) {
callback(null, './uploads')
},
filename: function(req, file, callback) {
console.log(file)
callback(null, file.fieldname + '-' + Date.now() +
path.extname(file.originalname))
}
})
app.post('/reactTest',function(req,res) {
var uploads = multer({
storage: storages,
fileFilter: function(req, file, callback) {
var ext = path.extname(file.originalname);
if (ext !== '.png' && ext !== '.jpg' && ext !== '.gif' && ext !== '.jpeg') {
res.send('Only images are allowed');
}
else {
fs.exists('./uploads/'+file.originalname, function(exists) {
console.log(exists);
if(exists) {
res.send('images already uploaded');
}
else {
callback(null, true);
}
})
}
}
}).single('user.uploadContent');
uploads(req, res, function(err) {
console.log(req.body);
res.send('File is uploaded');
})
})
app.get('/',function(req,res) {
var localTutor=require('./child.js');
localTutor.NodeTutorial()();
res.writeHead(200,{'Content-Type':'text/html'});
res.write('<form action="fileUpload" method="post" enctype="multipart/form-data">');
res.write('<input type="file" name="files" >');
res.write('<br><input type="submit" >');
res.write('</form>');
res.send();
//return res.send({error:true,message:'working'});
//res.render('html');
})
app.post('/fileUpload',function(req,res) {
var uploads = multer({
storage: storages
}).single('files');
uploads(req, res, function(err) {
if(err) {
throw err;
}
return res.send({status:'file uploaded'});
})
})
}
front-end
handleSubmit=(values,event)=> {
console.log(values);
const forms=new FormData(event.target);
let promise=fetch('http://localhost:8080/reactTest', {
method:'POST',
mode:'CORS',
body:forms,
headers:{
}
}).then(res =>res.json()).then(result=>console.log(result))
}
when i uploaded a file it returns status as "file uploaded", but the file is doesn't uploaded to the directory.I don't know what the issue here is?
I am also attaching the code to create a restful api at front-end side.
as #wdetac said , remove app.use(fileupload()); then add var path=require('path'); to your routes.js file
a working example
views/index.ejs
<form action="fileUpload" method="post" enctype="multipart/form-data"
id="form-id">
<input type="file" id="file-select" name="files" multiple/><br/>
<input type="text" name="email" id="email"><br>
<button type="submit" id="upload-button">Upload</button>
</form>
<script>
var form = document.getElementById('form-id');
var fileSelect = document.getElementById('file-select');
var uploadButton = document.getElementById('upload-button');
form.onsubmit = function(event) {
event.preventDefault();
var files = fileSelect.files;
var formData = new FormData();
for (var i = 0; i < files.length; i++) {
var file = files[i];
if (!file.type.match('image.*')) {
continue;
}
formData.append('files', file, file.name);
}
var email = document.getElementById('email').value;
formData.append('email',email);
let promise=fetch('http://localhost:8080/reactTest', {
method:'POST',
mode:'CORS',
body:formData
}).then(res =>res.json()).then(result=>console.log(result))
}
</script>
routes.js
app.post('/reactTest',function(req,res) {
var uploads = multer({
storage: storages,
fileFilter: function(req, file, callback) {
var ext = path.extname(file.originalname);
if (ext !== '.png' && ext !== '.jpg' && ext !== '.gif' && ext !== '.jpeg') {
res.send('Only images are allowed');
}
else {
fs.exists('uploads/'+file.originalname, function(exists) {
console.log(exists);
if(exists) {
res.send('images already uploaded');
}
else {
callback(null, true);
}
})
}
}
}).single('files');
uploads(req, res, function(err) {
console.log('----------',req.body);
res.send('File is uploaded');
})
})

Resources