I am new to Node JS, so things are not coming easy to me. The scenario is I have input field which will accept multiple files.
<input id="upload-input" type="file" name="uploads[]" multiple="multiple">
in my JS script I grab the the change event of this field, and create a post request to my uploader app which is running in different port using formData and ajax post method
$('#upload-input').on('change', function() {
var files = $(this).get(0).files;
if (files.length > 0) {
var formData = new FormData();
formData.append('directory', "path/to/directory");
for (var i = 0; i < files.length; i++) {
var file = files[i];
formData.append('uploads[]', file, file.name);
}
$.ajax({
url: 'https://myurl.com:3000/upload',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(data) {
console.log(data);
},
});
}
});
Now the file is sending and in my backend I can upload that using formidable, but the problem is I cannot get the directory value, Here is my code
require('dotenv').load();
var express = require('express');
var app = express();
var path = require('path');
var formidable = require('formidable');
var fs = require('fs');
var session = require('express-session');
app.set('views', __dirname + '/public');
app.use('/uploads', express.static(process.env.USER_UPLOADS))
var cors=require('cors');
app.use(cors({origin:true,credentials: true}));
app.post('/upload', function(req, res) {
var user_folder = "path/to/directory/";
var form = new formidable.IncomingForm();
form.multiples = true;
form.uploadDir = path.join(__dirname, process.env.USER_UPLOADS + user_folder);
form.on('file', function(field, file) { fs.rename(file.path, path.join(form.uploadDir, file.name)); });
form.on('error', function(err) { console.log('An error has occured: \n' + err); });
form.on('end', function() { res.end('success'); });
form.parse(req);
});
var server = app.listen(3000, function(){
console.log('Server listening on port 3000');
});
I tried
console.log(req.body)
but it returns undefined, So how can I get the directory value from my backend?
Thanks in advance.
To fix your issue, I made some changes to your main app's server file
i.e. server.js/app.js/index.js anyone that applies to you. See changes below:
require('dotenv').load();
var express = require('express');
var app = express();
var path = require('path');
var bodyParser = require('body-parser');
var formidable = require('formidable');
var fs = require('fs');
var session = require('express-session');
var cors=require('cors');
app.set('views', __dirname + '/public');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cors({ origin:true, credentials: true }));
app.use('/uploads', express.static(process.env.USER_UPLOADS));
app.post('/upload', function(req, res) {
var user_folder = "path/to/directory/";
var form = new formidable.IncomingForm();
form.multiples = true;
form.uploadDir = path.join(__dirname, process.env.USER_UPLOADS + user_folder);
form.on('file', function(field, file) { fs.rename(file.path, path.join(form.uploadDir, file.name)); });
form.on('error', function(err) { console.log('An error has occured: \n' + err); });
form.on('end', function() { res.end('success'); });
// Note the changes here
form.parse(req, (error, fields, files) => {
console.log(JSON.stringify({
fields, // { directory: "path/to/directory" }
files // contains the uploaded files
}), null, 2);
});
});
var server = app.listen(3000, function(){
console.log('Server listening on port 3000');
});
According to the docs at here, form.parse can take an optional callback function.
Parses an incoming node.js request containing form data. If cb is provided, all fields and files are collected and passed to the callback:
form.parse(req, function(err, fields, files) {
// ...
});
Related
I created some code (a simple file uploader) that works well all on one file. I would like to start breaking up the code into several files. I would like to have a routes.js (to control the routes), imports.js (that contains my function) and my server. I am having problems calling my imports from the route. I am getting error imports is not a function. Thank you!!
Server.js -----------------------------------------------------------
var express = require('express');
var app = express();
var passport = require('passport');
var ejs = require('ejs');
var bodyParser = require('body-parser');
var imports = require('./src/import.js');
var port = process.env.PORT || 8080;
app.use(express.static('public'));
require('./src/import')(imports);
require('./app/routes.js')(app, imports);
app.listen(port);
console.log('The app is running on port ' + port)
routes.js-----------------------------------------------------------
module.exports = function (app, imports) {
//home Page
app.get('/', function (req, res) {
res.render('index.ejs');
});
app.post('/import', imports(){});
};
import.js---------------------------------------------
var multer = require('multer');
var fs = require('fs');
module.exports = function (imports) {
var imports = multer({ dest: 'C:/Users/ron/temp/' });
var type = imports.single('file');
imports( type, function (req, res) {//removed type
var fileType = req.file.type;
console.log('output' + req.file);
console.log(fileType);
var file = __dirname + "/" + req.file.name;
fs.readFile(req.file.path, function (err, data) {
fs.writeFile(file, data, function (err) {
if (err) {
console.log(err);
} else {
var fileName = req.file.originalname;
response = {
message: 'File uploaded successfully',
fileinfo: req.file,
filename: fileName
};
}
console.log(response);
res.end(JSON.stringify(response));
var filePath = req.file.destination + req.file.originalname;
fs.rename(req.file.destination + req.file.filename, req.file.destination + req.file.originalname, function (err) {
if (err) console.log('ERROR:' + err);
console.log('the path is...' + filePath);
console.log('the name is...' + fileName);
});
});
});
});
};
Single file solution..................................................
var express = require('express');
var app = express();
var passport = require('passport');
var ejs = require('ejs');
var bodyParser = require('body-parser');
var multer = require('multer');
var fs = require('fs');
var port = process.env.PORT || 8080;
var imports = multer({ dest: 'C:/Users/ron/temp/' });
var type = imports.single('file');
var urlencodedParser = bodyParser.urlencoded({extended: false});
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static('public'));
app.get('/', function (req, res) {
res.render('index.ejs');
});
app.post('/import', type, function (req, res) {//removed type
var fileType = req.file.type;
console.log('output' + req.file);
console.log(fileType);
var file = __dirname + "/" + req.file.name;
fs.readFile(req.file.path, function (err, data) {
fs.writeFile(file, data, function (err) {
if (err) {
console.log(err);
} else {
var fileName = req.file.originalname;
response = {
message: 'File uploaded successfully',
fileinfo: req.file,
filename: fileName
};
}
console.log(response);
res.end(JSON.stringify(response));
var filePath = req.file.destination + req.file.originalname;
fs.rename(req.file.destination + req.file.filename, req.file.destination + req.file.originalname, function (err) {
if (err) console.log('ERROR:' + err);
console.log('the path is...' + filePath);
console.log('the name is...' + fileName);
});
});
});
});
app.listen(port);
console.log('The app is running on port ' + port)
Note that every function you include in your router must have reqest and response object as a parameter.
Change your function as :
function imports (req,res){
//your code
}
module.exports ={
imports:imports
}
And now import this function in router file.
I have uploaded the image in to a local directory using Busboy and passed
the path of the image to the MongoDB using Mongoose but now I unable to
retrieve the path
to display the image in my ejs view. I'm new to this nodejs. Please help me
to display the image.
Thank you Very much in Advance :)
var express = require('express'); //Express Web Server
var busboy = require('connect-busboy'); //middleware for form/file upload
var path = require('path'); //used for file path
var fs = require('fs-extra'); //File System - for file manipulation
var mongoose = require('mongoose');
var mongoClient = require('mongodb').mongoClient;
var objectId = require('mongodb').ObjectId;
var app = express();
app.use(busboy());
app.use(express.static(path.join(__dirname, 'public')));
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost:27017/postname');
/* ==========================================================
Create a Route (/upload) to handle the Form submission
(handle POST requests to /upload)
Express v4 Route definition
============================================================ */
app.set('view engine','ejs');
app.use(express.static(__dirname + '/public'));
var nameSchema = mongoose.Schema({
newfile: Object,
path: String
});
var compileSchema = mongoose.model('foods', nameSchema);
app.get('/', function(req, res, next) {
res.render('index',{'title': 'New post app'});
});
app.route('/')
.post(function (req, res, next) {
var fstream;
req.pipe(req.busboy);
req.busboy.on('file', function (fieldname, file, filename) {
console.log("Uploading: " + filename);
//Path where image will be uploaded
fstream = fs.createWriteStream(__dirname + '/public/uploads/' + filename);
var dirname = path.join(__dirname + '/public/uploads/' + filename);
file.pipe(fstream);
//mongo save
var paths = new compileSchema({newfile : dirname, passReqToCallback: true});
paths.save(function(err){
if(err) throw err;
compileSchema.find({newfile: dirname}, (err, result) =>{
console.log();
return result;
});
});
fstream.on('close', function () {
console.log("Upload Finished of " + filename);
//where to go next
res.redirect('/profile');
});
});
});
app.get('/profile', (req, res)=>{
res.render('profile',{photo: req.result});
});
var server = app.listen(3030, function() {
console.log('Listening on port %d', server.address().port);
});
My Ejs file is :
<img src='<%= photo.newfile %>' >
This is the typical process of writing and reading from Mongodb using Mongoose. I have not checked whether your streaming and other things work fine but the db workflow would be better this way.
var express = require('express'); //Express Web Server
var busboy = require('connect-busboy'); //middleware for form/file upload
var path = require('path'); //used for file path
var fs = require('fs-extra'); //File System - for file manipulation
var mongoose = require('mongoose');
var mongoClient = require('mongodb').mongoClient;
var objectId = require('mongodb').ObjectId;
var app = express();
app.use(busboy());
app.use(express.static(path.join(__dirname, 'public')));
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost:27017/postname');
/* ==========================================================
Create a Route (/upload) to handle the Form submission
(handle POST requests to /upload)
Express v4 Route definition
============================================================ */
app.set('view engine','ejs');
app.use(express.static(__dirname + '/public'));
//You can import your schema like this
const Name = require('./name');
var compileSchema = mongoose.model('foods', nameSchema);
app.get('/', function(req, res, next) {
res.render('index',{'title': 'New post app'});
});
//I have changed your route since it seems to be clashing with the above
app.post('/save' ,function (req, res, next) {
var fstream;
req.pipe(req.busboy);
req.busboy.on('file', function (fieldname, file, filename) {
console.log("Uploading: " + filename);
//Path where image will be uploaded
fstream = fs.createWriteStream(__dirname + '/public/uploads/' + filename);
file.pipe(fstream);
var dirname = path.join(__dirname + '/public/uploads/' + filename);
//mongo save
fstream.on('close', function () {
//You can either save to mongodb after streaming closes or while it is streaming but in this case I will do it after.
console.log("Upload Finished of " + filename);
//where to go next
//Declare your schema object here
let name = new Name({
newfile:'Whatever you want to store here',
path: path
});
//Save your declared schema like this
name.save((err) => {
if(err) throw err;
console.log(`saved : ${name}`);
//When you redirect here, it will go to /profile route
res.redirect('/profile');
});
});
});
});
app.get('/profile', (req, res)=>{
//You must retrieve from mongodb your object here if this is where you want the object to be
//{} empty query will find all objects in the table
Name.find({}, (err, result) => {
if(err) throw err;
//after everything was found, send it to front end
res.render('profile',{
photo: req.result,
//Now your 'compileSchema' object is available at front end as 'result' object
result:result
});
});
});
var server = app.listen(3030, function() {
console.log('Listening on port %d', server.address().port);
});
name.js (create one schema js file for each table you will be working with)
let mongoose = require('mongoose');
let Schema = mongoose.Schema;
let compileSchema = new Schema({
newfile: Object,
path: String
});
let Compile = mongoose.model('Compiles', compileSchema);
module.exports = Compile;
Check first that you are receiving and streaming file correctly. If you are, it must work fine. Also, I don't know why you want to save a newfile:object field but all you really need to do is save the path to the image file then retrieve it where you need to use the image and use the path as the <img src='path'> Refer to the comments.
I am a real noob in JS and Node and am trying to render a JADE view from JSON received from a REST API. When i run the http.request as a standalone it works just fine, but when i start adding modules and the render stamens, I cannot get the http request function to execute.
When i run it in debug it just skips to the end statement. i cannot figure out why.
any help would be really appreciated TIA.
var http = require('http');
module.exports = function() {
var options = {
host: '41.193.214.130',
port: 2510,
path: '/eiftidemo/clt_list',
method: 'GET'
};
var clientsDatag;
http.request(options, function(res) {
var body = '';
//none of these statemnst excecute
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
var clientsData = JSON.parse(body);
var clientsDatag = clientsData;
// this stament doesn't execute either
debugger;
});
}).end();
debugger;
res.render('listlxr', {
details: clientsDatag
});
};
here is the calling script:
var express = require('express');
var bodyParser = require('body-parser');
var tweetList = require('./tweet-list');
var clientList = require('./lxr-clients')
var app = express();
app.set('view engine', 'jade');
app.use(bodyParser.urlencoded({
extended: false
}))
app.get('/', function(req, res) {
res.render('index');
});
app.post('/get_tweets', function(req, res) {
var screen_name = req.body.handle;
var tweets = tweetList(res, screen_name);
});
app.get('/get_clients', function(req, res) {
var clientd = clientList(res, req);
});
var server = app.listen(3000, function() {
console.log('Our App is running at http://localhost:3000');
});
many thanks to anyone who can help
app.get('/get_clients', function(req, res) {
var options = {
host: '41.193.214.130',
port: 2510,
path: '/eiftidemo/clt_list',
method: 'GET'
};
http.request(options, function(details) {
res.render('listlxr', {
details: details
});
});
});
Try adding an error-handler and see if you get anything there:
var request= http.request(options, function(res) {...});
request.on('error', function(err){
// Handle error
});
I am trying to upload images to node.js express
bodyParser need a middleware to handle the image file , or it will reply
token undefine
I use Multer as middle ware , as this said, the req.file should hole a array of information, than I can use req.file.image.path to get the file path and other information, than I can save it as a file.
Here is the problem, I upload an image from Postman, I only write console.log(req.file) it shows undefined.
If I try to write req.file.image.path to get the file path, the error is image undefined, it seems like I didn't use multer well, so the req.file didn't hold the data information, Should I create some temp folder to multer or...?
app.js
var express = require('express')
,bodyParser = require('body-parser')
,app = express()
,multer = require('multer')
,binary = require('binary')
,fs = require('fs')
,util= require('util')
,http = require('http')
,multer = require('multer')
,upload = multer({ dest: '/Node/file-upload/uploads/' });
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies.
app.use(bodyParser.json({limit: '5mb'}));
songs = require('./routes/route');
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
app.post('/upload',songs.upload);
route.js
var mongoose = require('mongoose');
var uri = "mongodb://1111:1111#ds061365.mongolab.com:61365/aweitest";
mongoose.connect(uri);
// we're connected!
var db = mongoose.connection.db;
var BSON = require('bson').BSONPure;
var binary = require('binary');
var body = require('body-parser');
var fs = require('fs');
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, '/Node/file-upload/uploads/');
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '-' + Date.now());
}
});
var upload = multer({ storage : storage}).single('image');
db.on('error', console.error.bind(console, 'connection errrrrrrrror:'));
db.once('open', function() {
console.log("mongodb is connected!!");
});
exports.upload = function(req, res) {
upload(req,res,function(err) {
console.log(req.file);
fs.readFile(req.file.image.path, function (err, data){
var dirname = "/Node/file-upload/uploads/";
var newPath = dirname + req.body.filename;
fs.writeFile(newPath, data, function (err) {
if(err) {
return res.end("Error uploading file.");
}
res.end("File is uploaded");
});
});
});
};
error
TypeError: Cannot read property 'image' of undefined
at c:\Users\awei\WebstormProjects\untitled\routes\girlshanlder.js:107:28
You need to set the filename before send the image in the Postman as shown here
Cheers.
Full code for uploading images in your MySQL database and in folder too.
Just define the module and install multer and path and save it.
var multer = require('multer');
var path = require('path');
var storage = multer.diskStorage({
destination: function(req, file, callback) {
callback(null, './uploadimages')
},
filename: function(req, file, callback) {
callback(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname))
}
})
app.post('/imginsert',multer({
storage: storage,
fileFilter: function(req, file, callback) {
var ext = path.extname(file.originalname)
if (ext !== '.png' && ext !== '.jpg' && ext !== '.gif' && ext !== '.jpeg')
{
return callback(res.end('Only images are allowed'), null)
}
callback(null, true)
}
}).single('img'), function(req, res) {
/*img is the name that you define in the html input type="file" name="img" */
var data = {
table_column_name(your database table column field name) :req.file
};
var query = connection.query("Insert into tablename set ?" ,data,function(err, rows)
{
if (err)
throw err;
res.redirect('/blog');
});
console.log(query.sql);
console.log(req.file);
});
How can I download a file that is in my server to my machine accessing a page in a nodeJS server?
I'm using the ExpressJS and I've been trying this:
app.get('/download', function(req, res){
var file = fs.readFileSync(__dirname + '/upload-folder/dramaticpenguin.MOV', 'binary');
res.setHeader('Content-Length', file.length);
res.write(file, 'binary');
res.end();
});
But I can't get the file name and the file type ( or extension ). Can anyone help me with that?
Update
Express has a helper for this to make life easier.
app.get('/download', function(req, res){
const file = `${__dirname}/upload-folder/dramaticpenguin.MOV`;
res.download(file); // Set disposition and send it.
});
Old Answer
As far as your browser is concerned, the file's name is just 'download', so you need to give it more info by using another HTTP header.
res.setHeader('Content-disposition', 'attachment; filename=dramaticpenguin.MOV');
You may also want to send a mime-type such as this:
res.setHeader('Content-type', 'video/quicktime');
If you want something more in-depth, here ya go.
var path = require('path');
var mime = require('mime');
var fs = require('fs');
app.get('/download', function(req, res){
var file = __dirname + '/upload-folder/dramaticpenguin.MOV';
var filename = path.basename(file);
var mimetype = mime.lookup(file);
res.setHeader('Content-disposition', 'attachment; filename=' + filename);
res.setHeader('Content-type', mimetype);
var filestream = fs.createReadStream(file);
filestream.pipe(res);
});
You can set the header value to whatever you like. In this case, I am using a mime-type library - node-mime, to check what the mime-type of the file is.
Another important thing to note here is that I have changed your code to use a readStream. This is a much better way to do things because using any method with 'Sync' in the name is frowned upon because node is meant to be asynchronous.
Use res.download()
It transfers the file at path as an “attachment”. For instance:
var express = require('express');
var router = express.Router();
// ...
router.get('/:id/download', function (req, res, next) {
var filePath = "/my/file/path/..."; // Or format the path using the `id` rest param
var fileName = "report.pdf"; // The default name the browser will use
res.download(filePath, fileName);
});
Read more about res.download()
For static files like pdfs, Word docs, etc. just use Express's static function in your config:
// Express config
var app = express().configure(function () {
this.use('/public', express.static('public')); // <-- This right here
});
And then just put all your files inside that 'public' folder, for example:
/public/docs/my_word_doc.docx
And then a regular old link will allow the user to download it:
My Word Doc
Here's how I do it:
create file
send file to client
remove file
Code:
let fs = require('fs');
let path = require('path');
let myController = (req, res) => {
let filename = 'myFile.ext';
let absPath = path.join(__dirname, '/my_files/', filename);
let relPath = path.join('./my_files', filename); // path relative to server root
fs.writeFile(relPath, 'File content', (err) => {
if (err) {
console.log(err);
}
res.download(absPath, (err) => {
if (err) {
console.log(err);
}
fs.unlink(relPath, (err) => {
if (err) {
console.log(err);
}
console.log('FILE [' + filename + '] REMOVED!');
});
});
});
};
In Express 4.x, there is an attachment() method to Response:
res.attachment();
// Content-Disposition: attachment
res.attachment('path/to/logo.png');
// Content-Disposition: attachment; filename="logo.png"
// Content-Type: image/png
'use strict';
var express = require('express');
var fs = require('fs');
var compress = require('compression');
var bodyParser = require('body-parser');
var app = express();
app.set('port', 9999);
app.use(bodyParser.json({ limit: '1mb' }));
app.use(compress());
app.use(function (req, res, next) {
req.setTimeout(3600000)
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept,' + Object.keys(req.headers).join());
if (req.method === 'OPTIONS') {
res.write(':)');
res.end();
} else next();
});
function readApp(req,res) {
var file = req.originalUrl == "/read-android" ? "Android.apk" : "Ios.ipa",
filePath = "/home/sony/Documents/docs/";
fs.exists(filePath, function(exists){
if (exists) {
res.writeHead(200, {
"Content-Type": "application/octet-stream",
"Content-Disposition" : "attachment; filename=" + file});
fs.createReadStream(filePath + file).pipe(res);
} else {
res.writeHead(400, {"Content-Type": "text/plain"});
res.end("ERROR File does NOT Exists.ipa");
}
});
}
app.get('/read-android', function(req, res) {
var u = {"originalUrl":req.originalUrl};
readApp(u,res)
});
app.get('/read-ios', function(req, res) {
var u = {"originalUrl":req.originalUrl};
readApp(u,res)
});
var server = app.listen(app.get('port'), function() {
console.log('Express server listening on port ' + server.address().port);
});
you can use res.sendFile()... the Sample-download.xlsx should be in the same directory as this function.
const downloadFile = (req,res) => {
var options = {
root: path.join(__dirname),
};
let fileName = "Sample-download.xlsx";
res.sendFile(fileName, options, function (err) {
if (err) {
console.log(err);
return res.status(500).json({ success: false, message: "internal server error. please try again later" });
} else {
console.log("Sent:", fileName, "at", new Date().toString());
}
});
}