【问题标题】:FileStream from busboy to MongoDB从 busboy 到 MongoDB 的 FileStream
【发布时间】:2019-03-27 17:38:34
【问题描述】:

所以我有一个来自 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...

【问题讨论】:

    标签: javascript stream busboy


    【解决方案1】:

    无需将文件保存到磁盘,您可以使用某种流接口将其直接从 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 到达0 时,|| 运算符将执行res.end 方法。

    【讨论】:

    • 谢谢!但是 1. 我不想使用 GridFS(不需要大于 16mb 的文件)和 2. 我需要将此文件与其他一些元数据一起保存,例如谁上传了它等。我该怎么做?
    • 遗憾的是,我看不到另一个用于较小文件的 mongo 流式客户端。您可以将文件累积在缓冲区中并简单地保存它,我将在本周尝试更新答案。你能@Zorobay 发布一个小文件上传的链接吗?那么它应该很简单。
    【解决方案2】:

    因此,虽然 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);
    });
    

    【讨论】:

      猜你喜欢
      • 2020-02-16
      • 2016-08-18
      • 2015-05-27
      • 1970-01-01
      • 2016-08-23
      • 1970-01-01
      • 1970-01-01
      • 2014-06-12
      • 1970-01-01
      相关资源
      最近更新 更多