Store image in mongo db using mongoose - node.js

Instead of storing file directly into mongodb I want to store using mongoose library. How to use mongoose library using the code frame same?
Update:: Saved in mongoose library. Now it uploads all of the file but how can I just store only the docx file instead of image file. And uploading anyother file should say invalid file.
update 2:: Resolved with the issue. Now capable of only allowing docxx file. Now need to add filename with extention as mentioned in the comment section. How to use that part of code.
Middleware::upload.js
const util = require("util");
const multer = require("multer");
const GridFsStorage = require("multer-gridfs-storage");
const mongoose = require('mongoose');
const Grid = require('gridfs-stream');
const mongoURI ='mongodb://localhost:27017/file_uploaded';
const promise = mongoose.connect(mongoURI, { useNewUrlParser: true });
const conn = mongoose.connection;
let gfs;
conn.once('open',() => {
gfs = Grid(conn, mongoose.mongo);
gfs.collection('uploads');
});
var storage = new GridFsStorage({
db: promise,
options: { useNewUrlParser: true, useUnifiedTopology: true },
file: (req, file) => {
return new Promise((resolve, reject) => {
if (file.mimetype === 'application/vnd.openxmlformats-
officedocument.wordprocessingml.document') {
resolve({
bucketName: 'words'
})
***//Add filename inorder to maintain original final name with
extention***
//const filename = `${Date.now()}-
bezkoder-${file.originalname}`;
//return filename;
} else {
reject(Error("File type has been rejected"));
}
});
}
});
var uploadFile = multer({ storage: storage }).single("file");
var uploadFilesMiddleware = util.promisify(uploadFile);
module.exports = uploadFilesMiddleware;

You dont need to use GridFsStorage. Try below code.
// file-controller.js
const express = require('express');
const mongoose = require('mongoose');
const multer = require('multer');
const router = express.Router();
const multerStorage = multer.memoryStorage();
const upload = multer({ storage: multerStorage, });
const imageSchema = mongoose.Schema({
image: { data: Buffer, contentType: String },
}, { timestamps: true });
const ImageModel = mongoose.model('images', imageSchema);
router.post('/upload', upload.single('image'), async (req, res, next) => {
const image = { data: new Buffer.from(req.file.buffer, 'base64'), contentType: req.file.mimetype }
const savedImage = await ImageModel.create(image);
res.send(savedImage);
});
router.get('/getImage/:id', async (req, res, next) => {
const { id: _id } = req.params;
// If you dont use lean(), you wont decode image as base64
const image = await ImageModel.findOne({ _id }).lean().exec();
res.send(image);
});
module.exports = router;
Serve route via express.
const express = require('express');
const FileController = require('./file-controller');
const app = express();
// Mongo DB connection code ...
// Serve static files code ...
app.use('/file', FileController);
app.listen(3000, () => console.log(`Example app listening on port ${port}!`));

Related

Storing Images in Mongodb With GridFS Using Express Server

I am trying to upload, save and display images in MongoDB using express server and GridFS.
Data is sent with FormData with vue.js on the front-end and that part works well.
Images are getting to the server, and it stores that data, but I can not display the uploaded image, instead I get this
It displays the Image in some encoding I guess.
Here is server code for receiving, storing and displaying images.
const express = require('express')
const mongodb = require('mongodb')
const path = require('path')
const crypto = require('crypto')
const mongoose = require('mongoose')
const multer = require('multer')
const GridFsStorage = require('multer-gridfs-storage')
const Grid = require('gridfs-stream')
const methodOverride = require('method-override')
const config = require('../../config/keys')
const morgan = require('morgan')
const images = express()
// MIDDLEWARE
images.use(methodOverride('_method'))
// images.use(morgan("default"))
// MONGO URI
const mongoURI = config.dbUrl
// CREATE MONGO CONNECTION
const conn = mongoose.createConnection(mongoURI)
// INITALIZE GRID FS
let gfs
conn.once('open', () => {
gfs = Grid(conn.db, mongoose.mongo)
gfs.collection('uploads')
})
// CREATING STORAGE ENGINE
const storage = new GridFsStorage({
url: mongoURI,
file: (req, file) => {
return new Promise((resolve, reject) => {
const filename = file.originalname
const fileInfo = {
filename,
bucketName: 'uploads'
}
resolve(fileInfo)
})
}
})
const upload = multer({ storage })
// POST REQUEST UPLOADS FILE TO DATABASE
images.post('/', upload.single('image'), (req, res) => {
console.log('POST REQUEST TO HTTP://LOCALHOST:3000/API/BACKEND/IMAGES/')
res.json(req.file)
console.log(req.file)
})
// GET REQUEST
images.get('/', async (req, res) => {
console.log('GET REQUEST TO HTTP://LOCALHOST:3000/API/BACKEND/IMAGES/')
const posts = await load();
res.send(await posts.find({}).toArray())
})
images.get('/:filename', (req, res) => {
gfs.files.findOne({ filename: req.params.filename }, (err, file) => {
// Check if file
if (!file || file.length === 0) {
return res.status(404).json({
err: 'No file exists'
});
}
// Check if image
if (file.contentType === 'image/jpeg' || file.contentType === 'image/png') {
// Read output to browser
const readstream = gfs.createReadStream(file.filename);
readstream.pipe(res);
} else {
res.status(404).json({
err: 'Not an image'
});
}
});
});
// LOADING FUNCTION FOR MONGODB
async function load() {
const client = await mongodb.MongoClient.connect
(`${config.dbUrl}`, {
useNewUrlParser: true,
useUnifiedTopology: true
});
return client.db('myCluster').collection('uploads.files');
}
module.exports = images
Every help would be nice and much appreciated! Thanks! :)

Unable to export a variable from a node module and use that variable across my node-express application

I've isolated my database connection and GridfsStorage code into its own file because I need to be able to access gridfs storage and multer upload across my application. The problem I'm facing here is that I'm unable to export the gfs variable, as shown below. I can successfully access and use the dbInstance and upload variables, just not the gfs variable, and I'm struggling to understand why that is the case.
When I try accessing gfs in my controller or in my route file, it is undefined and no methods associated with it are available.
I'm looking for a pointer to what is happening here and possible solutions. Any help is appreciated.
db.js:
const express = require('express');
const path = require('path');
const crypto = require('crypto');
const dotenv = require('dotenv');
const multer = require('multer');
const GridFsStorage = require('multer-gridfs-storage');
const Grid = require('gridfs-stream');
const mongoose = require('mongoose');
dotenv.config();
// Set up mongoose connection
const mongoDB = process.env.DB_URL;
const conn = mongoose.connect(mongoDB, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
});
mongoose.Promise = global.Promise;
const dbInstance = mongoose.connection;
let gfs;
dbInstance.once('open', () => {
gfs = Grid(dbInstance.db, mongoose.mongo);
gfs.collection('fileUploads');
});
const storage = new GridFsStorage({
//url: mongoDB,
db: dbInstance,
file: (req, file) => {
return new Promise((resolve, reject) => {
crypto.randomBytes(32, (err, buff) => {
if (err) return reject(err);
const filename = buff.toString('hex') + path.extname(file.originalname);
const fileInfo = {
filename: filename,
bucketName: 'fileUploads',
};
resolve(fileInfo);
});
});
},
});
var upload = multer({ storage });
module.exports = {
dbInstance,
upload,
gfs,
};
Export an object and set a property on it. Objects are passed by reference.
So:
const gfs = {grid: undefined}
dbInstance.once('open', () => {
gfs.grid = Grid(dbInstance.db, mongoose.mongo);
gfs.grid.collection('fileUploads');
});
...
module.exports = {
dbInstance,
upload,
gfs,
};

Need some help for better understanding of the code

This is a working code so just need to understand some parts will be helpful.
upload.js::
const util = require("util");
const multer = require("multer");
const GridFsStorage = require("multer-gridfs-storage");
const mongoose = require('mongoose');
const Grid = require('gridfs-stream');
const mongoURI ='mongodb://localhost:27017/file_uploaded_new';
const promise = mongoose.connect(mongoURI, { useNewUrlParser: true });
const conn = mongoose.connection;
**let gfs;
conn.once('open',() => {
gfs = Grid(conn, mongoose.mongo);
gfs.collection('uploads');
});**
**var storage = new GridFsStorage({**
db: promise,
**options: {useNewUrlParser: true, useUnifiedTopology: true }**,
file: (req, file) => {
return new Promise((resolve, reject) => {
if (file.mimetype === 'application/vnd.openxmlformats-
officedocument.wordprocessingml.document') {
resolve({
bucketName: 'words',
filename: `${file.originalname}`
})
} else {
reject(Error("File type has been rejected"));
}
});
}
});
**var uploadFile = multer({storage: storage}).single("file");**
**var uploadFilesMiddleware = util.promisify(uploadFile);
module.exports = uploadFilesMiddleware;**
Need to know specifically the bold part of the code. Got the source code but without explanation. So would really be helpful to understand it.

while uploading image I cannot see the content

I have a problem uploading image file to my mongoDB using gridFS, but for some reason this doesn't work
this is my code :
const config = require("config");
const express = require("express");
const router = express.Router();
const dbURI = config.get("mongoURI");
const multer = require("multer");
const crypto = require("crypto");
const path = require("path");
const GridFsStorage = require("multer-gridfs-storage");
var storageImage = new GridFsStorage({
url: dbURI,
file: (req, file) => {
return new Promise((resolve, reject) => {
crypto.randomBytes(16, (err, buf) => {
if (err) {
return reject(err);
}
const filename = buf.toString("hex") + path.extname(file.originalname);
const fileInfo = {
filename: filename,
bucketName: "user_images"
};
resolve(fileInfo);
});
});
}
});
const uploadImage = multer({ storageImage });
router.post("/uploadImage", uploadImage.single("userImg"), (req, res) => {
console.log("uploading");
console.log(req.file);
res.json({ msg: "file uploaded successfully" });
});
module.exports = router;
when I console .log req.file I get undefined, does anyone know what the problem is?
I found the problem:
const uploadImage = multer({ storageImage });
it should be
const uploadImage= multer({storage:storageImage});

middleware is an object instead of a function

I'm trying to make a file upload API using multer gridFS, I used the documentation but I'm missing something:
this is my code:
const config = require("config");
const express = require("express");
const router = express.Router();
const dbURI = config.get("mongoURI");
const multer = require("multer");
const crypto = require("crypto");
const path = require("path");
const GridFsStorage = require("multer-gridfs-storage");
var storage = new GridFsStorage({
url: dbURI,
file: (req, file) => {
return new Promise((resolve, reject) => {
crypto.randomBytes(16, (err, buf) => {
if (err) {
return reject(err);
}
const filename = buf.toString("hex") + path.extname(file.originalname);
const fileInfo = {
filename: filename,
bucketName: "uploads"
};
resolve(fileInfo);
});
});
}
});
const upload = multer({ storage });
router.post("/upload", upload.single("file"), (req, res) => {
res.json({ msg: "file uploaded successfully" });
});
I get an error TypeError: Router.use() requires a middleware function but got a Object which basically tells me that upload.single is not a function, what is my error?
I found the mistake, I was missing module.exports = router;

Resources