从服务员到 MongoDB 的 FileStream
FileStream from busboy to MongoDB
所以我有一个来自 busboy 的传入 FileStream,我想将其保存到 MongoDB。我想我需要将它作为 File
或某种缓冲区才能保存它。我确定我可以通过先使用 fs
将其保存到磁盘然后读取它来做到这一点,但这似乎很麻烦。到目前为止,这是我的完整路线代码:
// Upload a new study plan
router.route("/add").post((req, res, next) => {
let busboy = new Busboy({headers: req.headers});
// A field was recieved
busboy.on('field', function (fieldname, val, valTruncated, keyTruncated) {
if (req.body.hasOwnProperty(fieldname)) { // Handle arrays
if (Array.isArray(req.body[fieldname])) {
req.body[fieldname].push(val);
} else {
req.body[fieldname] = [req.body[fieldname], val];
}
} else { // Else, add field and value to body
req.body[fieldname] = val;
}
});
// A file was recieved
busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
const saveTo = path.join('.', filename);
let readFile = null;
file.on("data", () => {
console.log("Got file data!");
})
file.on("end", () => {
//How do I save the file to MongoDB?
})
});
// We're done here boys!
busboy.on('finish', function () {
//console.log(req.body);
console.log('Upload complete');
res.end("That's all folks!");
});
return req.pipe(busboy);
});
我想将 {"pdf": file}
附加到我的 req.body
中,其中包含其余数据...
无需将文件保存到磁盘,您可以使用某种流媒体接口将其直接从 busboy
流式传输到 mongo - 我不确定您希望如何保存文件,但如果这只是一个简单的文件结构,我想你应该使用 Mongo's GridFS.
我假设您从某个地方获得了您的连接和客户端,所以我们将只使用它。我们需要来自客户端的 GridFS 存储桶:
const db = client.db(dbName);
const bucket = new mongodb.GridFSBucket(db);
我们要保存文件时会用到它:
// A file was recieved
busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
const saveTo = path.join('.', filename);
// here we PIPE the file to DB.
file.pipe(bucket.openUploadStream(saveTo));
});
现在还有一个问题是在文件实际保存时做出响应 - 因为这是异步完成的。所以我们需要像这样计算 运行 个操作:
// place this in the request callback.
// here's our counter - we'll increment it for each operation started.
let ops = 0;
const dec = () => --ops || res.end("That's all folks!");
现在我们稍微更改上面的代码,以便在文件保存到 Mongo:
之前我们不会响应
// A file was recieved
busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
ops++; // we increment ops for each file saved
const saveTo = path.join('.', filename);
// here we PIPE the file to DB (pass the db and collection here).
file.pipe(bucket.openUploadStream(saveTo))
.on('finish', dec);
});
ops++; // we're waiting for finish of the request also so another increment
busboy.on('finish', dec);
如您所见,每次开始文件上传时,我们都会增加 ops,当它完成时,我们会减少它。当ops
到达0
时,||
运算符将执行res.end
方法。
所以虽然 Michal 的回答可能没有错,但这不是我想要的。我终于通过使用 Buffer
对象找到了解决方案。这是我的代码:
router.route("/add").post((req, res, next) => {
let busboy = new Busboy({headers: req.headers});
let buffers = [];
// A field was recieved
busboy.on('field', function (fieldname, val, valTruncated, keyTruncated) {
if (req.body.hasOwnProperty(fieldname)) { // Handle arrays
if (Array.isArray(req.body[fieldname])) {
req.body[fieldname].push(val);
} else {
req.body[fieldname] = [req.body[fieldname], val];
}
} else { // Else, add field and value to body
req.body[fieldname] = val;
}
});
// A file was recieved
busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
file.on("data", (data) => {
buffers.push(data);
});
file.on("end", () => {
req.body[fieldname] = Buffer.concat(buffers);
});
});
// We're done here boys!
busboy.on('finish', function () {
console.log(req.body);
const plan = new StudyPlan(req.body);
plan.save()
.then(_ => console.log("YEEAEH!"))
.catch(err => {console.log(err);});
res.end();
});
return req.pipe(busboy);
});
所以我有一个来自 busboy 的传入 FileStream,我想将其保存到 MongoDB。我想我需要将它作为 File
或某种缓冲区才能保存它。我确定我可以通过先使用 fs
将其保存到磁盘然后读取它来做到这一点,但这似乎很麻烦。到目前为止,这是我的完整路线代码:
// Upload a new study plan
router.route("/add").post((req, res, next) => {
let busboy = new Busboy({headers: req.headers});
// A field was recieved
busboy.on('field', function (fieldname, val, valTruncated, keyTruncated) {
if (req.body.hasOwnProperty(fieldname)) { // Handle arrays
if (Array.isArray(req.body[fieldname])) {
req.body[fieldname].push(val);
} else {
req.body[fieldname] = [req.body[fieldname], val];
}
} else { // Else, add field and value to body
req.body[fieldname] = val;
}
});
// A file was recieved
busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
const saveTo = path.join('.', filename);
let readFile = null;
file.on("data", () => {
console.log("Got file data!");
})
file.on("end", () => {
//How do I save the file to MongoDB?
})
});
// We're done here boys!
busboy.on('finish', function () {
//console.log(req.body);
console.log('Upload complete');
res.end("That's all folks!");
});
return req.pipe(busboy);
});
我想将 {"pdf": file}
附加到我的 req.body
中,其中包含其余数据...
无需将文件保存到磁盘,您可以使用某种流媒体接口将其直接从 busboy
流式传输到 mongo - 我不确定您希望如何保存文件,但如果这只是一个简单的文件结构,我想你应该使用 Mongo's GridFS.
我假设您从某个地方获得了您的连接和客户端,所以我们将只使用它。我们需要来自客户端的 GridFS 存储桶:
const db = client.db(dbName);
const bucket = new mongodb.GridFSBucket(db);
我们要保存文件时会用到它:
// A file was recieved
busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
const saveTo = path.join('.', filename);
// here we PIPE the file to DB.
file.pipe(bucket.openUploadStream(saveTo));
});
现在还有一个问题是在文件实际保存时做出响应 - 因为这是异步完成的。所以我们需要像这样计算 运行 个操作:
// place this in the request callback.
// here's our counter - we'll increment it for each operation started.
let ops = 0;
const dec = () => --ops || res.end("That's all folks!");
现在我们稍微更改上面的代码,以便在文件保存到 Mongo:
之前我们不会响应 // A file was recieved
busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
ops++; // we increment ops for each file saved
const saveTo = path.join('.', filename);
// here we PIPE the file to DB (pass the db and collection here).
file.pipe(bucket.openUploadStream(saveTo))
.on('finish', dec);
});
ops++; // we're waiting for finish of the request also so another increment
busboy.on('finish', dec);
如您所见,每次开始文件上传时,我们都会增加 ops,当它完成时,我们会减少它。当ops
到达0
时,||
运算符将执行res.end
方法。
所以虽然 Michal 的回答可能没有错,但这不是我想要的。我终于通过使用 Buffer
对象找到了解决方案。这是我的代码:
router.route("/add").post((req, res, next) => {
let busboy = new Busboy({headers: req.headers});
let buffers = [];
// A field was recieved
busboy.on('field', function (fieldname, val, valTruncated, keyTruncated) {
if (req.body.hasOwnProperty(fieldname)) { // Handle arrays
if (Array.isArray(req.body[fieldname])) {
req.body[fieldname].push(val);
} else {
req.body[fieldname] = [req.body[fieldname], val];
}
} else { // Else, add field and value to body
req.body[fieldname] = val;
}
});
// A file was recieved
busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
file.on("data", (data) => {
buffers.push(data);
});
file.on("end", () => {
req.body[fieldname] = Buffer.concat(buffers);
});
});
// We're done here boys!
busboy.on('finish', function () {
console.log(req.body);
const plan = new StudyPlan(req.body);
plan.save()
.then(_ => console.log("YEEAEH!"))
.catch(err => {console.log(err);});
res.end();
});
return req.pipe(busboy);
});