Delete .files and .chunk with GridFSBucket - node.js

I'm trying to delete both .files and .chunk data but all the posts that I have found are either outdated or do not apply to my issue.
This is my backend route:
const mongoose = require("mongoose");
const config = require("config");
const db = config.get("mongoURI");
let gfs;
const conn = mongoose.createConnection(db);
conn.once("open", () => {
gfs = new mongoose.mongo.GridFSBucket(conn.db, {
bucketName: "photos"
});
});
router.delete('/:imageID', async (req, res) => {
gfs.delete({_id: req.params.imageID, root:"photos"}, function(error){
test.equal(error, null);
}
Any ideas?

Solved! to succesfully delete GridFS .files and .chunks just find the obj_id and do gfs.delete( obj_id)
Code:
router.delete("/:imageID", auth, async (req, res) => {
try {
const post = await Post.findOne({ image: req.params.imageID });
console.log(post);
if (post.user != req.user.id) {
res.status(401).send("Invalid credentials");
}
// Here:
const obj_id = new mongoose.Types.ObjectId(req.params.imageID);
gfs.delete( obj_id );
await post.remove();
res.json("successfully deleted image!");
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
});

Related

The link to go to the `ejs` page does not work

I can't go to another ejs page.
Description
The link to go to the ejs page does not work
I have an existing project... Everything works in it...
Example: a transition is made from Index -> to a subpage.
In the current state of the project, the subpage is located at localhost:3000/0/articles/14
The subpage is filled with data from the database.
I did.
created my own Index page;
Index page- opens;
created my own About Subpage;
Result: switching from the Index page to About does not work.
Index.ejs
<h1>Index page</h1>
<a href="/about" >About-1. Описание</a> </br>
<a href="http://localhost:3000/About/" >About-2. Описание</a>
I added to the file routes.js
.get('/about', (req, res) => {
res.render('about');
})
The whole code routes.js
const multer = require('multer');
const rand = require('randomstring');
const filesStorage = multer.diskStorage({
destination: (req, file, next) => {
next(null, 'static/uploads/files');
},
filename: (req, file, next) => {
const ext = file.originalname.split('.').pop();
next(null, rand.generate({
length: 32,
charset: 'alphabetic'
}) + '.' + ext);
}
});
const filesUpload = new multer({
storage: filesStorage
});
const site = {
main: require('./controllers/main')
};
const cms = {
articles: require('./controllers/cms/articles'),
files: require('./controllers/cms/files'),
lang: require('./controllers/cms/lang'),
slideshow: require('./controllers/cms/slideshow')
};
module.exports = (app, passport) => {
app
.get('/', site.main.lang)
.get('/video', site.main.video)
.get('/slideshow', site.main.slideshow)
.get('/:lang', site.main.index)
/*articles*/
.get('/:lang/articles', site.main.index)
.get('/:lang/articles/:id', site.main.article)
.get('/:lang/panomuseum', site.main.panomuseum)
.get('/:lang/panomuseum/2', site.main.panomuseum2)
.get('/:lang/panotheatre', site.main.panotheatre)
/*My*/
// .get('/:lang/articles', site.main.index)
.get('/Index', site.main.index)
.get('/history', site.main.history)
// .get('/history', (req, res) => {
// res.render('history');
// })
.get('/about', (req, res) => {
res.render('about');
})
;
app
.get('/cms/lang', cms.lang.index)
.post('/cms/lang', filesUpload.any(), cms.lang.save)
.get('/cms/:lang/articles', cms.articles.index)
.post('/cms/articles/saveOrder', cms.articles.saveOrder)
.get('/cms/:lang/articles/add', cms.articles.add)
.post('/cms/:lang/articles/add', filesUpload.any(), cms.articles.postAdd)
.get('/cms/:lang/articles/:id/edit', cms.articles.edit)
.post('/cms/:lang/articles/:id/edit', filesUpload.any(), cms.articles.postEdit)
.get('/cms/:lang/articles/:id/delete', cms.articles.delete)
.get('/cms/:lang/articles/:id', cms.articles.subArticle)
.get('/cms/:lang/articles/add/:id', cms.articles.add)
.post('/cms/files/delete', cms.files.delete)
.post('/cms/files/saveFile', filesUpload.single('file'), cms.files.saveFile)
.post('/cms/files/saveThumb', filesUpload.single('thumb'), cms.files.saveThumb)
.get('/cms/slideshow', cms.slideshow.index)
.post('/cms/slideshow/save', filesUpload.any(), cms.slideshow.save);
return app;
controllers\main.js
const db = require('../db');
const fs = require('fs');
const path = require('path');
const config = require('../config.js');
class Main {
async video(req, res, next) {
const videoFolder = './static/video'
let videos = []
fs.readdirSync(videoFolder).forEach((file) => {
let extension = path.extname(file)
let filename = path.basename(file, extension)
videos.push({
file,
filename: parseInt(filename),
})
})
videos = videos.sort((a, b) => {
return a.filename - b.filename
})
return res.render('video', {
domain: config.express.domain,
videos,
})
}
async panomuseum(req, res) {
const article = await db.article.getByID(req.params.lang);
const sub = await db.article.getRoot(req.params.lang);
const files = await db.files.getByOwnerId(req.params.lang);
const lang = await db.lang.getById(req.params.lang);
return res.render('panomuseum', {
article,
sub,
files,
lang
});
}
async panomuseum2(req, res) {
const article = await db.article.getByID(req.params.lang);
const sub = await db.article.getRoot(req.params.lang);
const files = await db.files.getByOwnerId(req.params.lang);
const lang = await db.lang.getById(req.params.lang);
return res.render('panomuseum2', {
article,
sub,
files,
lang
});
}
async panotheatre(req, res) {
const article = await db.article.getByID(req.params.lang);
const sub = await db.article.getRoot(req.params.lang);
const files = await db.files.getByOwnerId(req.params.lang);
const lang = await db.lang.getById(req.params.lang);
return res.render('panotheatre', {
article,
sub,
files,
lang
});
}
async index(req, res) {
const article = await db.article.getByID(req.params.lang);
const sub = await db.article.getRoot(req.params.lang);
const files = await db.files.getByOwnerId(req.params.lang);
const lang = await db.lang.getById(req.params.lang);
const timeout = await db.settings.getByID("timeout");
const caption = await db.settings.getByID("caption");
return res.render("index", {
article,
sub,
files,
lang,
timeout,
caption,
domain: req.app.get("domain"),
});
}
// async history(req, res) {
// // const article = await db.article.getByID(req.params.lang);
// // const sub = await db.article.getRoot(req.params.lang);
// // const files = await db.files.getByOwnerId(req.params.lang);
// // const lang = await db.lang.getById(req.params.lang);
// // const timeout = await db.settings.getByID("timeout");
// // const caption = await db.settings.getByID("caption");
// return res.render("history", {
// domain: req.app.get("domain")
// });
// }
async history(req, res) {
console.log('Request for history page recieved');
return res.render("history");
}
async about(req, res) {
console.log('Request for about page recieved');
return res.render("about");
}
async menu(req, res) {
return res.render("menu", {
domain: req.app.get("domain"),
});
}
async slideshow(req, res) {
const slideshow = await db.files.getSlideshow();
const timer = await db.settings.getByID("timer");
return res.render("slideshow", {
slideshow,
timer,
domain: req.app.get("domain"),
});
}
async slide(req, res) {
const slideshow = await db.files.getByID(req.params.id);
const timer = await db.settings.getByID("timer");
return res.render("slideshow", {
slideshow: [slideshow],
timer,
domain: req.app.get("domain"),
});
}
async article(req, res) {
const article = await db.article.getByID(req.params.id);
const sub = await db.article.getSub(req.params.id);
const files = await db.files.getByOwnerId(req.params.id);
const id = req.params.id;
const lang = await db.lang.getById(req.params.lang);
const timeout = await db.settings.getByID("timeout");
const caption = await db.settings.getByID("caption");
return res.render("index", {
id,
article,
sub,
files,
lang,
timeout,
caption,
domain: req.app.get("domain"),
});
}
async lang(req, res) {
const langs = await db.lang.getAll();
let activeCount = 0;
for (let lang of langs) {
if (lang.value == 1) {
activeCount++;
}
}
if (activeCount == 0) {
return res.redirect("/0");
} else if (activeCount == 1) {
for (let lang of langs) {
if (lang.value == 1) {
return res.redirect("/" + lang.id);
}
}
}
const timeout = await db.settings.getByID("timeout");
return res.render("lang", {
langs,
timeout,
});
}
async openSlide(req, res) {
console.log("openSlide");
let files = await db.files.getSyncSmartHome();
parentIO.sockets.in("client").emit("goToUrl", {
message: "/slide/" + files[parseInt(req.params.id)].id,
});
return res.json({
success: true,
});
}
async openSlideshow(req, res) {
console.log("open slideshow");
parentIO.sockets.in("client").emit("goToUrl", {
message: "/slideshow",
});
return res.json({
success: true,
});
}
}
module.exports = new Main();

Fastifyis not defined and fastify-postgres Fastify.pg.connect not working

I have defined my fastify like so:
const fastify = require('fastify')({logger: true})
fastify
.register(require('./setup/envs'))
.after(async (err) => {
if (err) console.log(err);
fastify.register(require('./setup/db'))
await fastify.after()
fastify.register(require('./setup/jwt'))
await fastify.after()
fastify.register(require('./setup/auth'))
await fastify.after()
// load routes
// fastify.register(require('./routes/test'))
fastify.register(require('./routes/posts/index'), { prefix: '/posts' })
})
const start = async () => {
try {
await fastify.ready()
fastify.listen(3000)
} catch (e) {
fastify.log.error(e)
process.exit(1)
}
}
start();
Now in my post routes, I have the following:
const postRoutes = require('../../controllers/posts');
async function PostRoutes(fastify, options) {
fastify.addHook('preValidation', fastify.verifyJWT)
fastify.addHook('preHandler', function (req, reply, done) {
if (req.body) {
req.log.info({ body: req.body }, 'parsed body')
}
if (req.params) {
req.log.info({ params: req.body }, 'parsed params')
}
done()
})
// get all posts
fastify.get('/:limit/:page', postRoutes.getPosts)
fastify.post('/signup', async (req, reply) => {
// some code
const token = fastify.jwt.sign({ test: 'hello' })
reply.send({ token })
})
fastify.get(
"/test-auth",
async function(request, reply) {
return { test: 'auth' }
}
)
}
module.exports = PostRoutes;
and my controller file is the following:
const fastify = require('fastify');
const getPosts = async (req, reply) => {
try {
const client = await fastify.pg.connect()
const { rows } = await client.query(
'SELECT * FROM POSTS LIMIT $1 OFFSET $2;', [req.params.limit, req.params.offset],
)
client.release()
return rows
} catch (e) {
req.log.error('Getting posts failed with params')
throw new Error(e)
}
}
module.exports = {
getPosts,
};
The const client = await fastify.pg.connect() is giving me fastify is not defined and if I require it by adding const fastify = require('fastify') at the top, I get TypeError: Cannot read properties of undefined (reading 'connect').
the following is my db.js:
const fastifyPlugin = require('fastify-plugin');
const fastifyPostgres = require('fastify-postgres');
async function dbConnector (fastify, options) {
const dbUser = encodeURIComponent(fastify.config.DATABASE_USERNAME)
const dbPassword = encodeURIComponent(fastify.config.DATABASE_PASSWORD);
const dbHost = encodeURIComponent(process.env.DATABASE_HOST);
const dbName = encodeURIComponent(fastify.config.DATABASE_NAME);
fastify.register(fastifyPostgres, {
connectionString: `postgres://${dbUser}:${dbPassword}#${dbHost}/${dbName}`
})
}
// Wrapping a plugin function with fastify-plugin exposes the decorators
// and hooks, declared inside the plugin to the parent scope.
module.exports = fastifyPlugin(dbConnector);
I had to change my route to
fastify.get('/:limit/:page', (req, reply) => postRoutes.getPosts(fastify, req, reply))
and then I was able to access the fastify object in my controller.

Error: connect ECONNREFUSED 127.0.0.1:5000

I´ve the file cases.js to create the route I want:
const express = require("express");
const { requireSignin } = require("../controllers/auth");
const { getCases } = require("../controllers/cases");
const { scrapingData } = require("../scrapingData");
const router = express.Router();
router.get("/cases", requireSignin, scrapingData, getCases);
module.exports = router;
requireSignin from controllers/auth looks like this:
exports.requireSignin = expressJwt({
secret: process.env.JWT_SECRET,
userProperty: "auth",
});
scrapingData as middleware I have:
const updateMongoRecords = async () => {
mongoose.Promise = global.Promise;
mongoose.set("debug", true);
Case.deleteMany({}, (err, result) => {
if (err) {
console.log(err);
} else {
console.log("Successfully deleted all records");
}
});
const dataPath = Path.join(__dirname, "files", "covid-data.csv");
try {
let headers = Object.keys(Case.schema.paths).filter(
(k) => ["_id", "__v"].indexOf(k) === -1
);
await new Promise((resolve, reject) => {
let buffer = [],
counter = 0;
let stream = fs
.createReadStream(dataPath)
.pipe(csv())
.on("error", reject)
.on("data", async (doc) => {
stream.pause();
buffer.push(doc);
counter++;
// log(doc);
try {
if (counter > 10000) {
await Case.insertMany(buffer);
buffer = [];
counter = 0;
}
} catch (e) {
stream.destroy(e);
}
stream.resume();
})
.on("end", async () => {
try {
if (counter > 0) {
await Case.insertMany(buffer);
buffer = [];
counter = 0;
resolve();
}
} catch (e) {
stream.destroy(e);
}
});
});
} catch (e) {
console.error(e);
} finally {
process.exit();
}
};
exports.scrapingData = async (req, res, next) => {
const url = "https://covid.ourworldindata.org/data/owid-covid-data.csv";
const path = Path.resolve(__dirname, "files", "covid-data.csv");
const response = await Axios({
method: "GET",
url: url,
responseType: "stream",
});
response.data.pipe(fs.createWriteStream(path));
return new Promise((resolve, reject) => {
response.data.on("end", () => {
resolve(updateMongoRecords());
next();
});
response.data.on("error", (err) => {
reject(err);
});
});
};
And getCases.js inside controllers/cases I have:
const Case = require("../models/case");
exports.getCases = async (req, res) => {
const cases = await Case.find().then((cases) => res.json(cases));
};
With this code I am able to fetch in the route /cases all the cases in the client side (like postman) and it shows all of them. But the problem is that I can´t make any other requests (like signing out, which works fine if I don´t make the get request for the cases like before) afterwards because client (postman) gives the error: GET http://localhost:5000/signout
Error: connect ECONNREFUSED 127.0.0.1:5000
in case you want to see the code for signout is like this:
const express = require("express");
const { signup, signin, signout } = require("../controllers/auth");
const router = express.Router();
router.post("/signup", userSignupValidator, signup);
router.post("/signin", userSigninValidator, signin);
router.get("/signout", signout);
inside controllers/auth.js:
exports.signout = (req, res) => {
res.clearCookie("t");
return res.json({ message: "Signout successfully done" });
};
Any help on this??

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.

node.js Why data from post requests that is saved in a json file resets to initial empty array after restart server?

I am working with express node.js, and I am trying to save datas from post request in a json file. but for some reason when I restart the server, my data from post request was supposed to save in roomDB.json file doesnt remain instead it resets to initial empty array...
Could anyone please advice? thank you very much.
here is my code
//saving function
const fs = require("fs");
exports.save =(data, PATH) =>{
return new Promise((resolve, reject) => {
fs.writeFile(PATH, JSON.stringify(data), function(err) {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
// code in router file to make requests
const express = require("express");
const router = express.Router();
const fs = require("fs");
const rooms = ("./roomDB.json");
const { addRoom} = require("./rooms");
router.get("/", (req, res)=>{
fs.readFile("roomDB.json", (err, data)=>{
if(err) return res.status(400);
res.send(roomDB_PATH)
})
});
router.get("/:id", (req, res)=>{
res.send("connect to a room");
});
router.post("/", (req, res)=>{
let roomName = req.body;
if(!roomName.name){
res.status(404);
res.end();
return;
}
let room =addRoom(roomName.name);
res.status(201).send(room)
})
module.exports = router;
*/
const uuid = require("uuid");
let roomdatas;
const {save} = require("./save");
const roomDB_PATH = "roomDB.json";
try {
roomdatas = JSON.parse(fs.readFileSync(roomDB_PATH));
} catch (e) {
roomdatas = []
save(roomdatas, roomDB_PATH);
}
const addRoom = (roomName) => {
roomName = roomName.trim().toLowerCase();
const existingRoom = roomdatas.find((room) => room.name === roomName);
if (existingRoom) {
return { error: 'chatroom has existed' };
}
let room = {
name: roomName,
id: uuid.v4(),
messages: [],
users: [],
created: +new Date()
};
roomdatas.push(room);
save(roomdatas, roomDB_PATH);
return { room };
};
module.exports ={addRoom};
I'm assuming that you are encountering an error with the JSON.parse(fs.readFileSync(roomDB_PATH)); call. This code runs every time your server is started (when you import the file into your router file), and if it encounters an error it is resetting the file to an empty array. Try logging the error to see what is causing it. You're currently completely suppressing the error with no way to tell why it is failing.

Resources