trying to get uploads saving in MongoDB - mongodb

I currently have the following code, which saves the temp file to public/files I have tried to understand the MongoDB GridFS documentation but with no success.
I am wondering how do I get the files to save inside MongoDB GridFS instead of my public/file directory
I am aware I am missing the part where I need to send the uploaded file to mongodb - this is the part I don't know how to do.
In mongodb example they say to do something like:
fs.createReadStream('./myFile').pipe(
bucket.openUploadStream('myFile', {
chunkSizeBytes: 1048576,
metadata: { field: 'myField', value: 'myValue' },
})
);
however I am not using FS or do I need to upload the file to the temp and then do the fs
import formidable from 'formidable';
import { MongoClient, ObjectId } from 'mongodb';
var Grid = require('gridfs-stream');
export const config = {
api: {
bodyParser: false,
},
};
export default async (req, res) => {
const uri = process.env.MONGODB_URI;
let client;
let clientPromise;
const options = {};
client = new MongoClient(uri, options);
clientPromise = client.connect();
const clients = await clientPromise;
const database = clients.db('AdStitchr');
var gfs = Grid(database, client);
gfs.collection('uploads');
const form = new formidable.IncomingForm();
form.uploadDir = 'public/files';
form.keepExtensions = true;
form.parse(req, (err, fields, files) => {
var file = files.file;
console.log(JSON.stringify(file));
try {
const newFile = File.create({
name: `files\${file.newFilename}.mp3`,
});
res.status(200).json({ status: 'success' });
} catch (error) {
res.send(error);
}
});
};

Related

node js app - cannot do raw queries on admin in atlas?

ihave been using mongoose to create models and exporting schema, now i have toupload file in mongo db, Please check the code below.
errmsg: 'cannot do raw queries on admin in atlas',
const util = require("util");
const multer = require("multer");
//const { GridFsStorage } = require("multer-gridfs-storage");
const dbConfig = require("../config/db.config");
const GridFsStorage = require('multer-gridfs-storage');
var storage = new GridFsStorage({
url: dbConfig.url + dbConfig.database,
options: { useNewUrlParser: true, useUnifiedTopology: true },
file: (req, file) => {
const match = ["image/png", "image/jpeg" ,"application/pdf","text/plain"];
if (match.indexOf(file.mimetype) === -1) {
const filename = `${file.originalname}`;
return filename;
}
return {
bucketName: dbConfig.imgBucket,
filename: `${file.originalname}`
// filename: `${Date.now()}-srikanth-${file.originalname}`
};
}
});
var uploadFiles = multer({ storage: storage }).array("file", 10);
// var uploadFiles = multer({ storage: storage }).single("file");
var uploadFilesMiddleware = util.promisify(uploadFiles);
module.exports = uploadFilesMiddleware;
db.config
module.exports = {
url: "mongodb+srv://username:password#cluster0.fatnc.mongodb.net/",
database: "students",
imgBucket: "photos",
};

how to retrieve/download image from mongoDB using GridFS in Next.js

I have uploaded a few images in MongoDB but cannot retrieve the images. I'm new to Next js, can anyone explain how I can make a "/api/retrieve?fileName='...'" get API to retrieve images from the database. The handler is being executed first then the db connection message is showing.
import nc from "next-connect";
import mongoose from "mongoose";
import Grid from "gridfs-stream";
import { GridFsStorage } from "multer-gridfs-storage";
export const config = {
api: {
bodyParser: false,
},
};
Grid.mongo = mongoose.mongo;
let gfs;
const conn = mongoose.createConnection(
process.env.mongoURI,
{
useNewUrlParser: true,
useUnifiedTopology: true,
},
(err) => {
if (err) {
console.err("file DB connection error", err);
process.exit();
}
console.log("file DB connected!");
gfs = Grid(conn.db, mongoose.mongo);
gfs.collection("images");
}
);
export default async function handler(req, res) {
if (req.method === "GET") {
console.log("request query: ", req.query);
try {
const file = await gfs.files.findOne({ filename: req.query.filename });
const readStream = gfs.createReadStream(file.filename);
readStream.pipe(res);
} catch (error) {
res.send("not found");
}
}
}
Thanks in advance.

Upload image to mongoDB and get back the url of the image: Multer

I'm trying to upload an image to MongoDB, but when I visualize it in mongoCompass it only shows its "_id". So I don't know if it went through or not.
I need to:
Store the image in the DB
Get the image's URL after it's stored there.
I'm using Express, Multer, Body-parser, fs, mongoose
Here's my app.js
const express = require("express"),
app = express(),
bodyParser = require("body-parser"),
fs = require("fs"),
multer = require("multer"),
mongoose = require("mongoose");
mongoose.connect("mongodb://localhost/Images");
app.use(bodyParser.urlencoded(
{ extended:true }
))
app.set("view engine","ejs");
//Schema
var imgSchema = mongoose.Schema({
img:{data:Buffer,contentType: String,nom:String}
});
var image = mongoose.model("image",imgSchema);
// SET STORAGE
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads')
},
filename: function (req, file, cb) {
cb(null, 'uploaded-' + Date.now()+".png")
}
})
var upload = multer({ storage: storage })
app.get("/",(req,res)=>{
res.render("index");
})
app.get("/show",(req,res)=>{
image.find().toArray(function (err,result){
const imgArray = result.map(element =>element._id);
console.log(imgArray);
if(err){
return console.error(err);
}
res.send(imgArray)
})
});
app.post("/uploadphoto",upload.single('myImage'),(req,res)=>{
var img = fs.readFileSync(req.file.path);
var encode_img = img.toString('base64');
var final_img = {
contentType:req.file.mimetype,
image:new Buffer(encode_img,'base64'),
nom:"hi"
};
image.create(final_img,function(err,result){
if(err){
console.log(err);
}else{
console.log(result.img.Buffer);
console.log("Saved To database");
res.contentType(final_img.contentType);
res.send(final_img.image);
}
})
})
//Code to start server
app.listen(2000,function () {
console.log("Server Started at PORT 2000");
})
this is what mongo shows me
This is the image upload folder
Thank you in advance
Everything is here
This Github repo has the answer detailed.
https://github.com/AnasGara/Upload-Image-Express-Mutler

Next JS connection with Apollo and MongoDB

I am new to Next.js and using this example from Next.js https://github.com/zeit/next.js/tree/master/examples/api-routes-apollo-server-and-client.
However, the example is silent on MongoDB integration (also I could not find any other example for the same). I have been able to make database-connection but NOT able to use it in resolvers.
My Code
pages/api/graphql.js
import { ApolloServer } from 'apollo-server-micro'
import { schema } from '../../apollo/schema'
const MongoClient = require('mongodb').MongoClient;
let db
const apolloServer = new ApolloServer({
schema,
context: async () => {
if (!db) {
try {
const client = await MongoClient.connect(uri)
db = await client.db('dbName')
const post = await Posts.findOne()
console.log(post)
// It's working fine here
}
catch (e) {
// handle any errors
}
}
return { db }
},
})
export const config = {
api: {
bodyParser: false,
},
}
export default apolloServer.createHandler({ path: '/api/graphql' })
apollo/schema.js
import {makeExecutableSchema} from 'graphql-tools';
import {typeDefs} from './type-defs';
import {resolvers} from './resolvers';
export const schema = makeExecutableSchema({
typeDefs,
resolvers
});
apollo/resolvers.js
const Items = require('./connector').Items;
export const resolvers = {
Query: {
viewer(_parent, _args, _context, _info) {
//want to populate values here, using database connection
return { id: 1, name: 'John Smith', status: 'cached' }
},
...
}
}
I am stuck in the resolvers.js part. Don't know how to get the cached database connection inside resolvers.js. If I create a new database connection file, top-level await is not supported there, so how do I proceed?
If context is a function, whatever you return from the function will be available as the context parameter in your resolver. So if you're returning { db }, that's what your context parameter will be -- in other words, you can access it as context.db inside your resolver.

Mongoose save() does not work when putting documents in collection and uploading files using multer-gridfs-storage

I am trying to build a music app and while working on the back end for the app (using express), I am facing this weird issue of documents not saving in mongo collections.
I made a post route to which user submits form data, which contains the song's mp3 file and the name of the song (it will have more data later on).
I am using multer to parse multipart form data.
I am able to save the mp3 file to mongoDB using multer-gridfs-storage. I want to save the song info such as name, artists etc in a different collection and here is the schema for the collection:
import mongoose from 'mongoose';
const Schema = mongoose.Schema;
const SongsInfo = new Schema({
name: {
type: String,
required: true,
},
});
const Song = mongoose.model('Song', SongsInfo);
export default Song;
index.js file:
import Grid from 'gridfs-stream';
import GridFsStorage from 'multer-gridfs-storage';
const app = express();
const conn = mongoose.createConnection(mongoURI);
let gfs;
conn.once('open', () => {
console.log('Connected to mongodb');
gfs = Grid(conn.db, mongoose.mongo);
gfs.collection('songFiles');
});
// storage engine
const storage = new GridFsStorage({
url: mongoURI,
file: (req, file) => new Promise((resolve, reject) => {
crypto.randomBytes(16, (err, buf) => {
if (err) {
return reject(err);
}
const filename = buf.toString('hex') +
path.extname(file.originalname);
let fileInfo;
fileInfo = {
filename,
bucketName: 'songFiles',
};
resolve(fileInfo);
});
}),
});
let upload;
middleWare(app);
app.post('/api/uploadSong', async (req, res) => {
upload = multer({ storage }).any();
upload(req, res, async (err) => {
console.log('in');
if (err) {
// console.log(err);
return res.end('Error uploading file.');
}
const { name } = req.body;
// push a Song into songs collection
const songInfo = new Song({
name,
});
const si = await songInfo.save(); // (*)
console.log(songInfo);
res.json({
songInfo: si,
file: req.file,
});
});
});
On line (*) the server just freezes until the request gets timed out.
No errors shown on console. Don't know what to do :(
I solved the issue finally!
So what i did was bring the models in index.js file and changed up some stuff here and there..
index.js
const app = express();
mongoose.connect(mongoURI); //(*)
const conn = mongoose.connection; // (*)
let gfs;
conn.once('open', () => {
console.log('Connected to mongodb');
gfs = Grid(conn.db, mongoose.mongo);
gfs.collection('songFiles');
});
// models
const Schema = mongoose.Schema; //(***)
const SongsInfo = new Schema({
name: {
type: String,
required: true,
},
});
const Song = mongoose.model('Song', SongsInfo);
// storage engine
const storage = new GridFsStorage({
url: mongoURI,
file: (req, file) => new Promise((resolve, reject) => {
crypto.randomBytes(16, (err, buf) => {
if (err) {
return reject(err);
}
const filename = buf.toString('hex') + path.extname(file.originalname);
let fileInfo;
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
fileInfo = {
filename,
bucketName: 'imageFiles',
};
} else {
fileInfo = {
filename,
bucketName: 'songFiles',
};
}
resolve(fileInfo);
});
}),
});
let upload;
middleWare(app);
app.post('/api/uploadSong', async (req, res) => {
upload = multer({ storage }).any();
upload(req, res, async (err) => {
console.log('in');
if (err) {
return res.end('Error uploading file.');
}
const { name } = req.body;
// push a Song into songs collection
const songInfo = new Song({
name,
});
songInfo.save((er, song) => {
if (!er) {
res.send('err');
} else {
console.log(err, song);
res.send('err');
}
});
});
});
At line (***) I used the same instance of mongoose that was initialized.. in the previous file I imported it again from the package...
Kia ora!
For those stumbling here three years on. I came across this issue as well. Abhishek Mehandiratta has the answer hidden in their code snippet.
The Fix
I went from instantiating mongoose with:
connect(connStr)
to doing:
const conn = createConnection(connStr)
This is the breaking change. So for an easy fix, change your code back to using connect(...).
I too, followed the documentation and Youtube tutorials to alter my code in such a way. It's an unfortunate misleading for developers who have not encountered a need to understand the difference.
I changed it back, and now it's working again (even with 'multer-gridfs-storage'). You can reference the connection with:
import {connection} from "mongoose";
connection.once('open', ...)
Why is this happening?
BenSower writes up the differences between connect and createConnection here. So from my basic understanding of BenSower's write up, you're referencing the wrong connection pool when you create your 'Song' schema, and thus, referencing the wrong pool when saving. I guess this results in a time out, have not looked further, but I'm sure a more in-depth answer exists somewhere.
import mongoose from 'mongoose';
const Song = mongoose.model('Song', SongsInfo);
As BenSower states in their answer "For me, the big disadvantage of creating multiple connections in the same module, is the fact that you can not directly access your models through mongoose.model, if they were defined "in" different connections". They're spot on with this one. Having finally overcome this obstacle, I shall have a look into createConnection on another project. For now, good ol' connect() will fix this issue, and do just fine :D