英文:
How to get the filename of a mongodb GridFS file given its id?
问题
如果我知道存储在GridFS中的文件的Mongo ID,并且想要根据其fs.files文件名字段中存储的文件名下载它,但没有模型来调用集合,所以我不知道该如何对该集合进行查询。
这是我的server.js文件,其中我连接到数据库:
require('dotenv').config()
const mongoose = require('mongoose')
// 连接到mongoose
mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true })
.then(() => {
// 监听请求
app.listen(process.env.PORT, () => {
console.log(`Connected to MongoDB and listening on port`, process.env.PORT)
})
})
.catch((error) => {
// 如果MONGO_URI字符串具有错误的用户或密码,则引发错误
console.log(error)
})
在我的files controllers文件中,我有这个:
const mongoose = require('mongoose')
require('dotenv').config()
const fs = require('fs')
// 创建用于存储文件的存储桶
// 存储桶初始化为fs,并有2个集合:fs.files和fs.chunks
let bucket
let conn
mongoose.connection.on("connected", () => {
conn = mongoose.connections[0].db
bucket = new mongoose.mongo.GridFSBucket(conn)
})
const downloadFileByID = async (req, res) => {
const { id } = req.params
if (!mongoose.Types.ObjectId.isValid(id)){
return res.status(404).json({error: 'No such file'})
}
const mongooseID = new mongoose.Types.ObjectId(id)
// 获取文件名
const cursor = bucket.find({}) // find()返回一个FindCursor可迭代对象
let filename
for await (const file of cursor) {
if (file._id == id){
filename = file.filename
}
}
try{
bucket.openDownloadStream(mongooseID).pipe(fs.createWriteStream('./' + filename.filename))
res.send(filename)
} catch (error) {
res.status(400).json({error: "File not found, file ID does not exist"})
}
}
我用来查找文件名的循环不是最佳的,而且非常慢,但我没有找到另一种访问fs.files的filename字段的方法。尝试使用 bucket.find({_id: id})
似乎实际上找不到文件,它什么也不返回(我认为find()不接受任何参数)。然而,文档中指出应该有一种方法可以从fs.files集合中获取filename字段,但没有解释如何做到这一点。我对此很困惑...
此外,我还尝试直接从fs.files集合中查询,但由于我没有该集合的模型,所以没有模型名称来执行查询。大多数来源使用类似于 db.fs.files.findOne({_id: id})
的语法,但我收到一个错误,说db未定义。这个问题似乎很容易解决,但我已经卡住了好几天了。
任何帮助将不胜感激。
英文:
What if I know the mongo id of a file stored in gridFS, and want to download it under the filename that is stored in its fs.files filename field? I don't have a model to call the collection with, so I'm confused how I'm supposed to do a query on that collection.
This is my server.js file, where I connect to the database:
require('dotenv').config()
const mongoose = require('mongoose')
//connect to mongoose
mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true })
.then(() => {
// Listen for requests
app.listen(process.env.PORT, () => {
console.log(`Connected to MongoDB and listening on port`, process.env.PORT)
})
})
.catch((error) => {
//throws error if the MONGO_URI string has the wrong user or pw
console.log(error)
})
and in my files controllers file I have this:
const mongoose = require('mongoose')
require('dotenv').config()
const fs = require('fs')
//Create a bucket for storing files
//bucket is initialized to fs and has 2 collections: fs.files and fs.chunks
let bucket
let conn
mongoose.connection.on("connected", () => {
conn = mongoose.connections[0].db
bucket = new mongoose.mongo.GridFSBucket(conn)
})
const downloadFileByID = async (req, res) => {
const { id } = req.params
if (!mongoose.Types.ObjectId.isValid(id)){
return res.status(404).json({error: 'No such file'})
}
const mongooseID = new mongoose.Types.ObjectId(id)
//Get filename
const cursor = bucket.find({}) //find() returns a FindCursor iterable
let filename
for await (const file of cursor) {
if (file._id == id){
filename = file.filename
}
}
try{
bucket.openDownloadStream(mongooseID).pipe(fs.createWriteStream('./'+ filename.filename))
res.send(filename)
} catch (error) {
res.status(400).json({error: "File not found, file ID does not exist"})
}
}
The loop I do to find the filename is not optimal and very slow, but I haven't found another way to access the filename field of fs.files.
Doing bucket.find({_id: id})
doesn't seem to actually find the file, it returns nothing (I don't think find() takes any arguments). However, the documentations state that there should be a way to get the filename field from the fs.files collection, but doesn't explain how to do it. I'm pretty stuck on this...
Otherwise, I also tried directly querying from the fs.files collection, but since I have no model for that collection, I don't have a model name to do the query on. Most sources use a syntax similar to `db.fs.files.findOne({_id: id}), but I get an error saying that db is not defined. This issue seems easy to solve, but I've been stuck for days.
Any help would be so appreciated.
答案1
得分: 0
我已解决我的问题!答案非常简单,正如我所预期:
const files = conn.collection('fs.files')
const filename = await files.findOne({_id: mongooseID}, {projection:{filename : 1, _id : 0}})
英文:
I have solved my problem! The answer was pretty simple, as expected:
const files = conn.collection('fs.files')
const filename = await files.findOne({_id: mongooseID}, {projection:{filename : 1, _id : 0}})
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论