I am new to nodejs and want to know how to put a file into my system backend or even upload it to S3 etc.
Here are the file object:
req.body { homeColor: 'black',
guestColor: 'white',
thirdColor: 'red',
file:
{ webkitRelativePath: '',
lastModifiedDate: '2014-05-05T02:26:11.000Z',
name: '2014-05-05 10.26.11.jpg',
type: 'image/jpeg',
size: 1310720 },
title: 'tfuyiboinini' }
How to handle req.body.file so that it can be physically saved?
Please help and thanks!
long story short
var fs = require('fs');
app.post('/file-upload', function(req, res) {
var tmp_path = req.files.thumbnail.path;
var target_path = './public/images/' + req.files.thumbnail.name;
fs.rename(tmp_path, target_path, function(err) {
if (err) throw err;
fs.unlink(tmp_path, function() {
if (err) throw err;
res.send('File uploaded to: ' + target_path + ' - ' + req.files.thumbnail.size + ' bytes');
});
});
};
you can read more about it here:
http://www.hacksparrow.com/handle-file-uploads-in-express-node-js.html
First make sure your POST is encoded as enctype="multipart/form-data"....
In Express 4 you need to set the body parser in your server:
var bodyParser = require('dy-parser');
//...
var app = express();
//...
app.use(bodyParser()); // pull information from html in POST
var busboy = require('connect-busboy');
app.use(busboy());
In earlier version of Express you only needed to add the body parser from the framework itself and files will be store on the configured location:
app.use(express.bodyParser({limit: '10mb', uploadDir: __dirname + '/public/uploads' })); // pull information from html in POST
Since version 4 removed support for connect now you need to add your custom support for multipart/form data to parser multi/part POSTs, so you will have to to do something like:
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');
});
});
});
This topic already shared the correct answer so might It is helpful.
Also, please find the below solution.
var express = require('express');
var busboy = require('connect-busboy');
var path = require('path');
var fs = require('fs-extra');
var app = express();
app.use(busboy());
app.use(express.static(path.join(__dirname, 'public')));
app.route('/fileupload')
.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 + '/img/' + filename);
file.pipe(fstream);
fstream.on('close', function () {
console.log("Uploading process finish " + filename);
// res.redirect('back');
});
});
});
Related
I want to send a file:
// Upload a file from loca file-system to MongoDB
app.post('/api/file/upload', (req, res) => {
var filename = req.query.filename;
// here ..... request please
console.log(file + " and" + tempPath );
var writestream = gfs.createWriteStream({ filename: filename });
fs.createReadStream(__dirname + "/uploads/" + filename).pipe(writestream);
writestream.on('close', (file) => {
res.send('Stored File: ' + file.filename);
});
});
I want to send a file to mongoose (Gridfs), in this API test with Postman
How about using https://www.npmjs.org/package/gridfs-stream
var fs = require('fs');
var mongoose = require("mongoose");
var Grid = require('gridfs-stream');
var GridFS = Grid(mongoose.connection.db, mongoose.mongo);
app.post('/api/file/upload', (req, res) => {
var writestream = GridFS.createWriteStream({
filename: req.query.filename
});
writestream.on('close', function (file) {
callback(null, file);
});
fs.createReadStream(path).pipe(writestream);
});
Note that path is the path of the file on the local system.
I made a upload image to a document and saved the path to the MongoDB , While retrieving the Image, It is showing only the current image which is being uploaded. I want to show all the images which is uploaded to the database. Please help me to display all the images from the Data base.
Thank you 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 handlebars = require('handlebars');
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', 'hbs');
app.set('views', path.join(__dirname, 'views'));
app.use(express.static(__dirname + '/public'));
//You can import your schema like this
const Name = require('./name');
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, done){
console.log("Uploading" + filename);
//path where the file is being uploaded
fstream = fs.createWriteStream(__dirname + '/public/uploads/' + filename);
var dirname = path.join( 'uploads/' + filename);
file.pipe(fstream);
fstream.on('close', function(){
console.log("Upload Success" + filename);
let name = new Name({
path: dirname
});
name.save((err)=>{
if(err) throw err;
console.log(`saved : ${name}`);
res.redirect('/profile');
call(dirname);
});
});
});
});
function call(dirname){
Name.findOne({path: dirname}, (err, result) =>{
if(err) throw err;
var imgpath = result.path;
console.log("Saved check" + imgpath);
app.get('/profile', (req, res) =>{
res.render('profile',{
photo: req.result,
result : imgpath
});
});
});
}
var server = app.listen(3030, function() {
console.log('Listening on port %d', server.address().port);
});
My name.js file Mongoose Schema
let mongoose = require('mongoose');
let Schema = mongoose.Schema;
let compileSchema = new Schema({
path: String
});
let Compile = mongoose.model('Compiles', compileSchema);
module.exports = Compile;
Views File to display the image
<html>
<head>
<title>User Profile</title>
</head>
<body>
<h1>Welcome</h1>{{result}}<br><br>
<img src="{{result}}" height="180" width="250">
</body>
</html>
You are using findOne which only retrieves one object from the database. So if you want to retrieve all the images your code should be something like this :
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 handlebars = require('handlebars')
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', 'hbs')
app.set('views', path.join(__dirname, 'views'))
app.use(express.static(__dirname + '/public'))
// You can import your schema like this
const Name = require('./name')
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, done) {
console.log('Uploading' + filename)
// path where the file is being uploaded
fstream = fs.createWriteStream(__dirname + '/public/uploads/' + filename)
var dirname = path.join( 'uploads/' + filename)
file.pipe(fstream)
fstream.on('close', function () {
console.log('Upload Success' + filename)
let name = new Name({
path: dirname
})
name.save((err) => {
if (err) throw err
console.log(`saved : ${name}`)
res.redirect('/profile')
// removed call(), no need for it
})
})
})
})
app.get('/profile', (req, res) => {
// get all documents in the db by using find with no conditions
Name.find({}, (err, results) => {
if (err) throw err
var images = []
for (var result of results) {
images.push(result.path)
}
res.render('profile', {
images: images
})
})
})
var server = app.listen(3030, function () {
console.log('Listening on port %d', server.address().port)
})
And in the views you should loop through the images to display them, i believe you are using handlebars so the view should be something like this :
<html>
<head>
<title>User Profile</title>
</head>
<body>
<h1>Welcome</h1>
{{#each images}}
<img src="{{this}}" height="180" width="250">
{{/each}}
</body>
</html>
:) Hi!
I'm trying to figure out how to write uploading file directly into GridFs in express framework.
I wrote codes as below and the problem is that file event "file" is never emitted.
:(
var mongoose = require('mongoose');
var express = require('express');
var router = express.Router();
var fs = require('fs');
var Busboy = require('busboy');
router.get('/test', function(req, res){
res.render('test-gridfs', {title: 'TESTING GRIDFS'});
})
router.post('/test', function(req, res){
var busboy = new Busboy({headers: req.headers});
var gfs = req.gfs;
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
console.log('File [' + fieldname + ']: filename: ' + filename);
file.pipe(gfs.createWriteStream({
filename: 'moon.jpg',
content_type: 'image/jpg'
}))
});
busboy.on('finish', function() {
res.json({result: 'finish'});
});
req.pipe(busboy);
})
module.exports = router;
I am having some problems properly storing and retrieving files with GridFS. Currently, if I submit a .txt file I end up getting the contents of the file back, but if i submit a .doc file, I get a bunch of gibberish (like blackdiamonds with question marks in it).
My end goal is just to be able to submit the file and then allow someone to download the file later on a different request.
Writing Code:
router.post('/jobs/listing/:job/apply', multipartyMiddleware, function(req, res, next){
var myFile = req.files.file;
var conn = mongoose.createConnection('mongodb://localhost/test');
conn.once('open', function () {
var gfs = Grid(conn.db, mongoose.mongo);
var readfile = fs.createReadStream(myFile.path);
var f = readfile.pipe(gfs.createWriteStream({
filename: myFile.name
}));
f.on('close', function(){
console.log('File Added to GRIDFS');
res.end();
});
});
}
Reading Code:
var conn = mongoose.createConnection('mongodb://localhost/test');
conn.once('open', function () {
var gfs = Grid(conn.db, mongoose.mongo);
var readstream = gfs.createReadStream({
filename: req.file //set to desired filename
});
var f = readstream.pipe(res);
});
Any suggestions? I would really appreciate any help you can provide. Thanks.
Edit: Problem had to do with an uploading issue in angular.
Here's a simple implementation that I copied from another developer and modified. This is working for me:
https://gist.github.com/pos1tron/094ac862c9d116096572
var Busboy = require('busboy'); // 0.2.9
var express = require('express'); // 4.12.3
var mongo = require('mongodb'); // 2.0.31
var Grid = require('gridfs-stream'); // 1.1.1"
var app = express();
var server = app.listen(9002);
var db = new mongo.Db('test', new mongo.Server('127.0.0.1', 27017));
var gfs;
db.open(function(err, db) {
if (err) throw err;
gfs = Grid(db, mongo);
});
app.post('/file', function(req, res) {
var busboy = new Busboy({ headers : req.headers });
var fileId = new mongo.ObjectId();
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
console.log('got file', filename, mimetype, encoding);
var writeStream = gfs.createWriteStream({
_id: fileId,
filename: filename,
mode: 'w',
content_type: mimetype,
});
file.pipe(writeStream);
}).on('finish', function() {
// show a link to the uploaded file
res.writeHead(200, {'content-type': 'text/html'});
res.end('download file');
});
req.pipe(busboy);
});
app.get('/', function(req, res) {
// show a file upload form
res.writeHead(200, {'content-type': 'text/html'});
res.end(
'<form action="/file" enctype="multipart/form-data" method="post">'+
'<input type="file" name="file"><br>'+
'<input type="submit" value="Upload">'+
'</form>'
);
});
app.get('/file/:id', function(req, res) {
gfs.findOne({ _id: req.params.id }, function (err, file) {
if (err) return res.status(400).send(err);
if (!file) return res.status(404).send('');
res.set('Content-Type', file.contentType);
res.set('Content-Disposition', 'attachment; filename="' + file.filename + '"');
var readstream = gfs.createReadStream({
_id: file._id
});
readstream.on("error", function(err) {
console.log("Got error while processing stream " + err.message);
res.end();
});
readstream.pipe(res);
});
});
For anyone who ends up with this issue,
I had the same symptoms and the issue was a middleware. This was a gnarly bug. The response was being corrupted by connect-livereload.
Github Issue on busboy
Github Issue on gridfs stream
My response on a Similar Stack Overflow Issue
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());
}
});
}