我在 Heroku 上有一个应用程序,用于处理使用 GridFS 存储在 MongoDB Atlas 数据库中的音频文件。
这个应用程序使用Next.JS和express。
为了回答这个问题,让我们考虑一下我在 MongoDB Atlas 上 fs.files 集合中的这条记录。
_id: 46e737001837a062ce85dd4c
length: 214023
chunkSize: 261120
uploadDate: 2023-08-12T05:09:22.521+00:00
filename: "Audio_2023-09-18:14:39:26"
下面的代码(Block:server.get('/download', (req, res) => {...})是文件server.js的一部分,将是我的问题的对象:
const express = require('express'),
next = require('next'),
.....
mongoose = require('mongoose'),
Grid = require('gridfs-stream'),
mongoURI = process.env.MDB_URI_AUDIO;
mongoose.connect(mongoURI);
.....
const conn = mongoose.connection;
let gfs; // GridFS stream
conn.once('open', () => {
// Initialize GridFS stream
gfs = Grid(conn.db, mongoose.mongo);
});
.....
app.prepare().then(() => {
const server = express();
server.use(bodyParser.json({ limit: '1mb' }));
.....
server.get('/download', (req, res) => {
const gridFSBucket = new mongoose.mongo.GridFSBucket(conn.db);
const dataType = "audio/mp3";
if (req.query.afn) {
const filename = req.query.afn;
const downloadStream = gridFSBucket.openDownloadStreamByName(filename);
res.set('Content-Type', dataType); // Adjust the content type based on your audio format
res.set('Content-Disposition', `inline; filename="${filename}"`);
downloadStream.pipe(res)
}
if (req.query.id) {
// const recordID = req.query.id.toString(); // This does not work !
// const recordID = new ObjectID(req.query.id); // This does not work !
// const recordID = mongoose.Types.ObjectID(req.query.id); // This does not work !
const recordID = mongoose.Types.ObjectID.from(req.query.id); // This does not work !
const downloadStream = gridFSBucket.openDownloadStream(recordID);
res.set('Content-Type', dataType)
res.set('Content-Disposition', `inline; filename=BLABLAH`);
downloadStream.pipe(res);
}
});
.....
// Default route handler for Next.js pages
server.all('*', (req, res) => {
return handle(req, res);
});
const PORT = process.env.PORT || 3000; // Use Heroku-assigned port or default to 3000.
server.listen(PORT, (err) => {
if (err) throw err;
console.log(`> Ready on http://localhost:${PORT}`);
});
});
当我将浏览器指向此地址时:
https://myapp.herokuapp.com/download?afn=Audio_2023-09-18:14:39:26
我听到正在播放音频文件。这就是我所期望的。
当我将浏览器指向另一个地址时:
https://myapp.herokuapp.com/download?id=46e737001837a062ce85dd4c
我期望与第一个链接相同的事情,但它没有发生(我什么也没听到并收到错误)。 在第一个链接中,我使用文件名来获取音频, 对于第二个链接,我使用文件 ID 来获取它。
我的这部分代码很可能存在问题。但我错过了什么并且做错了什么?
if (req.query.id) {
.....
}
我希望有人能阐明这个问题并帮助我解决问题。
我对 Mongo 也有类似的问题。这与 Mongo 中 ID 的存储方式有关,您需要在使用 JS 查询之前进行此转换。
您不能简单地提供条目作为 GUID
"ec7427c4-567d-4e86-b4aa-e425fc2ec9b0"
您需要以十六进制格式提供
"Binary(Buffer.from("c42774ec7d56864eb4aae425fc2ec9b0", "hex"), 3)"
您可以使用此脚本进行转换
function convertGuidToHex(msGuid) {
let cleanGuid = msGuid.replace(/-/g, "").toLowerCase();
let hexString = cleanGuid.substring(6, 8) + cleanGuid.substring(4, 6) +
cleanGuid.substring(2, 4) + cleanGuid.substring(0, 2) +
cleanGuid.substring(10, 12) + cleanGuid.substring(8, 10) +
cleanGuid.substring(14, 16) + cleanGuid.substring(12, 14) +
cleanGuid.substring(16);
return `Binary(Buffer.from("${hexString}", "hex"), 3);
}