无法将缓冲区写入MongoDB GridFS

时间:2015-01-18 10:36:17

标签: javascript node.js mongodb express gridfs

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

这是我的闷热代码

product.js(路线/控制器)

    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);
                })

            })
        });
    }

我的DB对象来自哪里?我只是在初始化期间将它添加到猫鼬对象中。这就是代码的样子

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. 使用Native GridFS / GridStoire - 结果相同。
  5. 非常感谢任何帮助。

1 个答案:

答案 0 :(得分:3)

现在,你在这里错过的是“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成本和存储总是存在。