Connection time out in mongoose - node.js

I'm trying to upload a media file and few strings but I'm getting connection time out.
I want to upload media files like image , video with details of the file to MongoDB.
While the media file is uploaded the details which I enter do not .(description and name of the media file)
the error I'm getting is
[enter image description here][1]
MongooseError: Operation `mediainfos.insertOne()` buffering timed out after 10000ms at Timeout.<anonymous>
the code I'm using is
const conn = mongoose.createConnection(mongoURI, {
useNewUrlParser: true,
useUnifiedTopology: true,
},(err,database)=>{
db = database
})
let gfs;
conn.once("open", () => {
gfs = Grid(conn.db, mongoose.mongo);
gfs.collection("uploads");
});
const storage = new GridFsStorage({
url: mongoURI,
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});
//Upload Files to DB
app.post('/upload',upload.single('file'),async (req,res)=>{
const fileName = req.file != null ? req.file.filename :null
console.log("Media Name "+req.body.medianame)
const MediaInfo = new mediaInfo({
media_id:fileName,
media_name:req.body.medianame,
media_description:req.body.mediadescription
})
try{
const NewMediaInfo = await MediaInfo.save()
res.send("Works Fine")
}catch(error){
console.log(error)
}
res.redirect('/');
});
MediaInfo is the schema
const Mongoose = require("mongoose");
const Schema = Mongoose.Schema
let mediaInfo = new Schema({
media_id:{
type: String
},
media_name:{
type:String
},
media_description:{
type:String
},
});
module.exports = Mongoose.model('mediaInfos',mediaInfo)
ERROR IMAGE
[1]: https://i.stack.imgur.com/DqMdC.png

Related

How to upload image files in Postman and echo back the same image using Express and Multer

I am trying to upload a product using postman and anytime I submit; it sends back all the data with the image undefined as shown in this screenshot:
My controller file:
const gameRepository = require("../routes/repository")
exports.createGame = async (req, res, next) => {
try {
const PORT = 8000;
const hostname = req.hostname;
const url = req.protocol + '://' + hostname + ':' + PORT + req.path;
const payload = ({
name: req.body.name,
price: req.body.price,
category: req.body.category,
gameIsNew: req.body.gameIsNew,
topPrice: req.body.topPrice,
isVerOrient: req.body.IsVerOrient,
description: req.body.description,
image: url + '/imgs/' + req.path
});
let eachGame = await gameRepository.createGame({
...payload
});
console.log(req.body)
res.status(200).json({
status: true,
data: eachGame,
})
} catch (err) {
console.log(err)
res.status(500).json({
error: err,
status: false,
})
}
}
repository.js:
const Game = require("../models/gameModel");
exports.games = async () => {
const games = await Game.find();
return games;
}
exports.gameById = async id => {
const game = await Game.findById(id);
return game;
}
exports.createGame = async payload => {
const newGame = await Game.create(payload);
return newGame;
}
exports.removeGame = async id => {
const game = await Game.findById(id);
return game;
}
Multer.js:
const multer = require("multer");
const path = require("path");
// checking for file type
const MIME_TYPES = {
'imgs/jpg': 'jpg',
'imgs/jpeg': 'jpeg',
'imgs/png': 'png'
}
// Image Upload
const storage = multer.diskStorage({
destination: (req, file, cb ) => {
cb(null, path.join('../imgs'));
},
filename: (req, file, cb) => {
const name = file.originalname.split('').join(__);
const extension = MIME_TYPES[file.mimetype];
cb(null, name + new Date().toISOString() + '.' + extension);
}
});
module.exports = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 6
},
})
I am not sure about where I went wrong, that is why I need an external eye to help locate where the fault is coming from.
I have a feeling that I need to use body-parser or navigate into the image folder correctly, or multi-part form, I am not sure.
after many try and fail I finally figured it out.
turns out it has compatibility issues depending on your OS.
I use windows 10 and this resolved the issue for me
Here is my working code:
multer.js
const multer = require("multer");
const path = require("path");
// checking for file type
const MIME_TYPES = {
'image/jpg': 'jpg',
'image/jpeg': 'jpeg',
'image/png': 'png'
}
// Image Upload
const storage = multer.diskStorage({
destination: (req, file, cb ) => {
cb(null, ('storage/imgs/'));
},
filename: (req, file, cb) => {
const extension = MIME_TYPES[file.mimetype];
// I added the colons in the date of my image with the hyphen
cb(null, `${new Date().toISOString().replace(/:/g,'-')}.${extension}`);
}
});
module.exports = multer({
storage: storage
})
In my controller.js
const gameRepository = require("../routes/repository");
exports.createGame = async (req, res, next) => {
try {
const payload = {
name: req.body.name,
price: req.body.price,
category: req.body.category,
gameIsNew: req.body.gameIsNew,
topPrice: req.body.topPrice,
isVerOrient: req.body.IsVerOrient,
description: req.body.description,
image: req.file.filename,
};
let eachGame = await gameRepository.createGame({
...payload,
});
res.status(200).json({
status: true,
data: eachGame,
});
} catch (err) {
console.log(err);
res.status(500).json({
error: err,
status: false,
});
}
};
exports.getGames = async (req, res) => {
try {
let games = await gameRepository.games();
res.status(200).json({
status: true,
data: games,
});
} catch (err) {
console.log(err);
res.status(500).json({
error: err,
status: false,
});
}
};
exports.getGameById = async (req, res) => {
try {
let id = req.params.id;
let gameDetails = await gameRepository.gameById(id);
req.req.status(200).json({
status: true,
data: gameDetails,
});
} catch (err) {
res.status(500).json({
status: false,
error: err,
});
}
};
exports.removeGame = async (req, res) => {
try {
let id = req.params.id;
let gameDetails = await gameRepository.removeGame(id);
res.status(200).json({
status: true,
data: gameDetails,
});
} catch (err) {
res.status(500).json({
status: false,
data: err,
});
}
};
:
Postman output
Thanks to this great community.

how to upload products form and images to MongoDB atlas server?

I build a e-commerce website and i use fetch function to fetch the product data to the back end. like so
const form = document.querySelector('form');
form.addEventListener('submit', async(e) => {
e.preventDefault();
// get data from infront end
const title = form.title.value;
const category = form.category.value;
const hostKind = form.hostingKind.value;
const area = form.area.value;
const realStateDesc = form.realstateDisc.value;
const neighbourhoodDesc = form.neighbourhood.value;
const governorate = form.governorate.value;
const city = form.city.value;
const address = form.address.value;
const zipCode = form.zipCode.value;
const peopleAllowed = form.allowed.value;
const peopleMaxNum = form.maxnum.value;
const timeper = form.timeper.value;
const additional = form.additional.value;
const price = form.rentprice.value;
const photos = form.photos.value;
fetch(photos).then(response => {
console.log(response);
return response.blob();
})
//fetch data
try {
const res = await fetch('/host', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
title: title,
category: category,
hostKind: hostKind,
area: area,
realStateDesc: realStateDesc,
neighbourhoodDesc: neighbourhoodDesc,
governorate: governorate,
city: city,
address: address,
zipCode: zipCode,
peopleAllowed: peopleAllowed,
peopleMaxNum: peopleMaxNum,
timeper: timeper,
additional: additional,
price: price
})
});
//location.assign('/congrats');
} catch (err) {
console.log(err)
};
});
then i use GridFS and Multer to upload images inside this form to my MongoDB server like so
mongoose.connect(process.env.DB_CONNECT, { useNewUrlParser: true, useUnifiedTopology: true, useNewUrlParser: true, useCreateIndex: true, })
.then((result) => app.listen(3000))
.catch((err) => console.log(err));
const conn = mongoose.connection;
//init gfs
let gfs;
//const storage = new GridFSStorage({ db: conn });
conn.once('open', () => {
gfs = Grid(conn.db, mongoose.mongo);
gfs.collection('uploads');
});
//create storage engine
const storage = new GridFsStorage({
options: { useUnifiedTopology: true },
url: process.env.DB_CONNECT,
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 });
module.exports = upload;
the problem is that when i use my post request like that
router.post('/host', upload.single('photos'), controllpages.hostPost);
the photos don't save into my data base ,only the product info from controllpages.hostPost does.
and when i use the post request with any other function like so
router.post('/host', upload.single('photos'), (req , res) => {
console.log('Done')
};
the photos do save into my database but i lose the product info .
What should i do?

GridFSBucket Errors

When I try to use GridFSBucket from mongodb, chunks are created in fs.chunks collection, but no fs.files documents are created. Is there a reason why this maybe happening or is this a bug?
This will work on my local machine and docker on my local machine but not on docker on an AWS EC2.
const { MongoClient, GridFSBucket } = require('mongodb');
const crypto = require('crypto');
const dotenv = require('dotenv');
dotenv.config();
const url = process.env.MONGO_URI;
const dbName = 'tree_club';
const opts = { useUnifiedTopology: true };
const getPosts = async () => {
const client = await MongoClient.connect(url, opts);
const db = client.db(dbName);
const posts = await db.collection('post').find({}).sort({ created: -1 }).toArray();
client.close();
return posts;
};
const createPost = async (parent, { markdown, file }) => {
const client = await MongoClient.connect(url, opts);
const db = client.db(dbName);
const bucket = new GridFSBucket(db);
const fileId = file ? crypto.randomBytes(64).toString('hex') : undefined;
const { ops: [post] } = await db.collection('post').insertOne({
markdown,
fileId,
created: Date.now()
});
if (file) {
await new Promise(async (resolve, reject) => {
const { createReadStream } = await file;
const readStream = createReadStream();
const writeStream = bucket.openUploadStreamWithId(fileId, fileId);
readStream.pipe(writeStream);
readStream.on('error', () => {
console.log('error');
});
readStream.on('finish', () => {
resolve();
client.close();
});
});
} else {
client.close();
}
return post;
};
const pipeImage = async (req, res) => {
const client = await MongoClient.connect(url, opts);
const db = client.db(dbName);
const bucket = new GridFSBucket(db);
try {
const readStream = bucket.openDownloadStream(req.params.fileId);
readStream.pipe(res);
readStream.on('finish', () => {
client.close();
});
} catch (err) {
res.status(400).json('Image was not found');
}
};
module.exports = { getPosts, createPost, pipeImage };
I searched for the answer to this question and turns out there's an error in Node.js version 13 with streams.
I downgraded my Node.js version to 12 and the code above worked perfectly.

How to get files uploaded via multer using mongoose?

I'm using the below function to get the files uploaded by multer in mongodb.The request is returning empty array.
exports.getPhotos = async (req, res) => {
const photos = await Photo.find()
.then(photos => {
res.status(200).json(photos);
})
.catch(err => res.status(500).json({message: "Something went wrong"}));
};
and this is the schema of the image. Is there any way to get the files without specifying the schema?
const mongoose = require("mongoose");
const {ObjectId} = mongoose.Schema;
const photoSchema = new mongoose.Schema({
lenght: {
type: String,
},
chunkSize: {
type: String,
required: true
},
uploadDate: {
type: Date,
},
filename: {
type: String,
},
md5: {
type: String,
},
contentType: {
type: String,
},
});
module.exports = mongoose.model("Photo", photoSchema);
i use gridfs so it could upload larger files too . a piece of sample code below
//Connecting to mongo
const conn = mongoose.createConnection(mongoURI);
//Init gfs
let gfs;
conn.once('open', ()=>{
gfs = GridFsStream(conn.db, mongoose.mongo);
gfs.collection('uploads');
})
//Creating Storage engine
const storage = new GridFsStorage({
url:mongoURI,
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)
//bucket name should match the collection name
const fileInfo = {
filename:fileName,
bucketName:'uploads'
}
resolve(fileInfo);
})
})
}
})
const upload = multer({storage})
now use this upload const in your paths like the one below there are a few methods for upload like array , single and ... depends on number of files you are uploading . the 'uploadedFile' argument is the name of the file input and you should be consider setting it in your frontend.
app.post('/',upload.single('uploadedFile'),(req, res)=>{
res.json('file uploaded')
})
this upload middleware adds a files to your request which you can use to put file names in your database and later fetch it by that uniqe names with a route like the one below .
app.get('/:filename', (req, res)=>{
gfs.files.findOne({filename:req.params.filename},(err,file)=>{
if(!file || file.length === 0){
return res.status(404).json({
err:'No file Exists'
})
}
const readStream = gfs.createReadStream(file.filename);
readStream.pipe(res)
})
})

this.db.collection not function when retrieving files from mongo

I am trying to retrieve a file from mongodb atlas i am using gridfsstream and multer.It keeps giving me this error.
TypeError: this.db.collection is not a function
I can successfully upload but retrieving is not working.What am i missing here
const router = require("express").Router();
const multer = require("multer");
const { mongo, connection } = require("mongoose");
const config = require("../../config/main").db;
const Grid = require("gridfs-stream");
Grid.mongo = mongo;
var gfs = Grid(config);
// set up connection to db for file storage
const storage = require("multer-gridfs-storage")({
url: config,
file: (req, file) => {
return {
filename: file.originalname
};
}
});
// sets file input to single file
const singleUpload = multer({ storage: storage }).single("file");
router.get("/files", (req, res) => {
gfs.files.find().toArray((err, files) => {
if (!files || files.length === 0) {
return res.status(404).json({
message: "Could not find files"
});
}
return res.json(files);
});
I hope still help you, although it passed a few time!! I had the same error when I tried retrieving an image. Below is my code :
MongoClient.connect(config.Info.mongo_database, {}, (err, client) => {
if(err) { new Error("An error has occurred while this file is retrieving: "+ err); }
//throw the error: this.db.collection is not a function
let bucket = new mongo.GridFSBucket(client.db, {
bucketName: bucketName
});
bucket.openDownloadStreamByName(filename).pipe(response);
})
And I solved like this:
MongoClient.connect(config.Info.mongo_database, {}, (err, client) => {
if(err) { new Error("An error has occurred while this file is retrieving: "+ err); }
//Look this, I must to explicit database name, otherwise that error is thrown
let db = client.db('files_repository');
let bucket = new mongo.GridFSBucket(db, {
bucketName: bucketName
});
bucket.openDownloadStreamByName(filename).pipe(response);
})
It works for me now!!

Resources