javascript - 无法将缓冲区写入 MongoDB GridFS

标签 javascript node.js mongodb express gridfs

大家好,我花了将近一天的时间来弄清楚这个问题。我正在使用 multer 的 inMemory 标志从我的网页上传图像。明显的尝试是将从 multer 接收到的缓冲区写入 GridFs(更具体地说是 GridStore)。

这是我的multer代码

product.js(路由/ Controller )

    var DB = rek('database');
    var router = express.Router();
    var multer = require("multer");

    var uploadOptions = {inMemory:true, onFileUploadComplete: uploadDone}

    router.post('/product/:productId/images/', multer(uploadOptions), uploadImageResponse);

    function uploadDone(file) {
        var options = {
            name:file.name,
            mode:"w+",
            content_type:file.mimetype,
            w: "majority",
            chunkSize: 1024,
            metadata:file
        };

        var GridStore = new DB.GridStore(DB.connection, file.name, "w+", options);
        GridStore.open(function(err, GS){
            if(err) throw err;
            return GS.write(file.buffer, function(err, GS){
                console.log("file written");
                if(err) throw err;
                return GS.close(function(err, result){
                    if(err) throw err
                    console.log(result);
                })

            })
        });
    }

我的数据库对象来自哪里?我只是在初始化期间将它添加到 Mongoose 对象中。这是代码的样子

database.js

var mongoose = require("mongoose"),
    mongooseTimestamps = require("mongoose-concrete-timestamps"),
    autoIncrement = require("mongoose-auto-increment"),
    config = require("../config"),
    Grid = require("gridfs-stream");

mongoose.connect( config.database['development'].url + "" + config.database['development'].name );
var db = mongoose.connection;
db.once("open", function(err){
    if(err) throw err
    mongoose.GridStore = mongoose.mongo.GridStore
})
db.on("error",function(errMsg){
    console.log("Error Connecting to Mongo: " + errMsg);
});
mongoose.set('debug', true);

mongoose.plugin(mongooseTimestamps);
autoIncrement.initialize(db);
module.exports = mongoose;

因此,在无数次更改我的代码并得出相同的结果之后,这是我自己的状态——没有写入,没有错误

虽然我每次都从 mongoose 输出日志中得到这个

POST /product/1000/images 200 4.494 ms - 22
Mongoose: fs.chunks.ensureIndex([ [ 'files_id', 1 ], [ 'n', 1 ] ]) { w: 'majority' }  
Mongoose: fs.files.find({ filename: '2b08f506ed277eda45f9fc400c098aa1.jpg' }) { readPreference: 'primary', w: 'majority' }  
Mongoose: fs.chunks.find({ n: 0, files_id: ObjectId("54bb87aaabf2c0416a50c068") }) { readPreference: 'primary', w: 'majority' }

如果我错了请纠正我,但为什么当我“插入/写入”到 GridFS 时它会进行查找。到目前为止,我得到了这个输出,我的断点只得到了对 GridStore.open 的调用,我得到了正确的流,但是写入永远不会发生,也不会抛出任何错误。

到目前为止我尝试了什么

  1. 使用 Multer 的 InMemory - 结果相同
  2. 使用 Multer 的 dest 属性并将流从 fs 通过管道传输到 gridfs - 结果相同。
  3. 使用 gridfs-stream 模块 - 结果相同
  4. 使用原生 GridFS/GridStoire - 结果相同。

非常感谢任何帮助。

最佳答案

现在,您在这里错过的是“inMemory”选项中的“缓冲区”不是“非此即彼”,并不意味着内容保存在“内存中”。它实际上是数据的“副本”,也被发送到磁盘上的临时文件。

所以你是否设置“inMemory”并不重要,因为文件仍然会被创建(默认情况下在 /tmp 目录中)但是这些文件当然会在离开时取消链接范围:

var async = require('async'),
    express = require('express'),
    multer = require('multer'),
    fs = require('fs'),
    mongoose = require('mongoose'),
    Grid = require('gridfs-stream'),
    Schema = mongoose.Schema;

Grid.mongo = mongoose.mongo;
var app = express(),
    gfs = {};

// Set up multer middleware
app.use(
  multer({
    //inMemory: true
  })
);

// Register handler
app.post('/',function (req,res) {

  async.eachLimit(Object.keys(req.files), 10, function(file,callback) {
    var fileobj = req.files[file];

    var writeStream = gfs.createWriteStream({
      "filename": fileobj.fieldname
    });

    fs.createReadStream(fileobj.path).pipe(writeStream);

    writeStream.on('close',function() {
      console.log('done');
      callback();
    });

    writeStream.on('error',callback);

  },function(err) {
    if (err) {
      console.log(err);
      res.status(500).end();
    }
    res.status(200).end();
  });

});

mongoose.connect('mongodb://localhost/test');


// Start app listen and events
var server = app.listen(3000,function() {

  mongoose.connection.on('open',function(err) {
    if (err) throw err;
    // Set up connection
    gfs = Grid(mongoose.connection.db);
    console.log('listening and connected');
  });

});

当然还有一个简单的测试:

var FormData = require('form-data'),
    fs = require('fs'),
    http = require('http');

var fname  = 'GearsLogo.png';
var form = new FormData();
form.append(fname,fs.createReadStream(fname))

var request = http.request({
  method: 'post',
  port: 3000,
  headers: form.getHeaders()
});

form.pipe(request);

request.on('response',function(res) {
  console.log(res.statusCode);
});

交替调用与您的请求方法内联的中间件,和/或设置onFileUploadComplete() 处理程序而不是迭代req.files 的内容. “gridfs=stream”包可能是您必须上传内容的最简单的选择,并且尝试从作为副本的缓冲区工作并不会真正提供任何真正的优势,因为 IO 成本和存储始终存在。

关于javascript - 无法将缓冲区写入 MongoDB GridFS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28008731/

相关文章:

node.js - 身份验证失败 Mongoose

multithreading - NodeJS 批处理多处理 - 池中的子进程(或多线程)

node.js - 亚马逊 EC2 Ubuntu 实例 : Where should I upload the files to access them from the browser?

javascript - 自动调整 IFrame 大小

JavaScript 回调函数不处理传递参数

javascript - 匹配两个左括号

php - 使我的 Ajax 函数正常工作的正确语法

node.js - Node JS : How to Create Window?(无 HTML)

node.js - 如何在每次获得新的数据库条目时更新 html 而无需重新加载页面

mongodb - Meteor/ReactJS - UI 闪烁问题 : rendering twice before and after checking a database