Node JS , Express : upload file - node.js

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.

Related

how can I upload file in Node JS?

I have problem while trying to upload file.
I use mongo as database and reactjs for frontend.
file appears in the database but it does not appear in the project.
I wanna appear in the directory which I set in the code.
And this is backend API.
const express = require("express");
const fileRoutes = express.Router();
let File = require("../../models/File");
const multer = require("multer");
const fs = require("fs-extra");
const storageBase = require("../../config/keys").storageBase;
const isEmpty = require("is-empty");
const addDays = require("date-fns").addDays;
const moment = require("moment-timezone");
// const fileUpload = require("express-fileupload");
// app.use(fileUpload());
var storage = multer.diskStorage({
destination: function (req, file, cb) {
const { file_type, file_owner } = req.query;
const path =
`${storageBase}` +
`${file_type}/${moment(new Date()).tz("Asia/Shanghai").format("YYYY-MM/MM-DD")}/${file_owner}`;
if (!fs.existsSync(path)) {
fs.mkdirsSync(path);
}
cb(null, path);
},
filename: function (req, file, cb) {
cb(null, file.originalname);
}
});
var upload = multer({
storage: storage,
limits:{
files: 5,
fieldSize: 4096 * 1024 * 1024
}
});
fileRoutes
.route("/upload")
.post(upload.single("file_data"), function (req, res) {
const {
file_type,
file_description1,
file_description2,
file_description3,
file_owner,
file_owner_job,
file_register_date,
hour,
minute
} = req.query;
let file = new File({
file_type: file_type,
file_url: req.query.file_register_date + "/" + req.files.file_data.name,
file_description1: file_description1,
file_description2: file_description2,
file_description3: file_description3,
file_owner: file_owner,
file_owner_job: file_owner_job,
file_register_date: file_register_date + " " + hour + ":" + minute
});
file
.save()
.then(file => {
res.status(200).json({ file: "file uploaded successfully" });
})
.catch(err => {
res.status(400).send("upload failed");
});
});
module.exports = fileRoutes;
But file which I select for upload does not save in my project
If u know how to do pls help me.

File stream parsing with busboy and write directly into GridFs in express

:) 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;

Initializing Gridfs returns TypeError: string is not a function

I'm trying to write an uploaded file (such as an image) to a mongodb database. However when I try to initialize the gridfs-stream I get a Type Error. Here's my code:
var mongo = require('mongodb');
router.post('/createpost', cpUpload, function(req,res) {
var db = req.db;
var gfs = Grid(db,mongo);
var file = req.file;
var fileId = new ObjectId();
var writestream = gfs.createWriteStream({
filename: file.originalname,
mode: 'w',
content_type: file.mimetype,
metadata: req.body.postText,
});
fs.createReadStream(file.path).pipe(writestream);
writestream.on('close', function(file) {
res.send("Succcess!");
fs.unlink(file.path,function(err) {
if (err) {
console.log("Error: ", err);
console.log("DELETED: ", file.path);
}
});
});
});
I'm guessing it has something to do with me calling db as req.db but I make the db accessible to the router file with this code in app.js
var mongo = require('mongodb');
var monk = require('monk');
var db = monk('localhost:27017/test-api');
app.use(function(req,res,next) {
req.db = db;
req.mongo = mongo;
next();
});
I had the incorrect syntax for var Grid = require('gridfs-stream'); very easy fix.

Encoding Issue with Gridfs-stream, Multiparty Middleware

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

Store the uploaded files into file system in Express Js

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');
});
});
});

Resources