Unable to write buffer to MongoDB GridFS

假如想象 提交于 2019-12-24 13:19:44

问题


Hi guys i have spent almost a day trying to figure this one out. I'm using multer's inMemory flag to upload an image from my webpage. The obvious attempt is to write the buffer received from multer to GridFs (GridStore more specifically).

here is my multer code

product.js (route/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);
                })

            })
        });
    }

where is my DB object coming from? i'm just adding it to the mongoose object during initialisation. this is what the code looks like

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;

So this is currently myself up after changing my code countless number of times and arriving at the same result - No Writes, No errors

I do get this everytime though from the mongoose output log

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' }

Correct me if i'm wrong but why is it doing a find when i'm "inserting/writing" to GridFS. So far i get this output and my breakpoints only get me as far as the call to GridStore.open, I get the stream back correctly but then the write never happens and no error is thrown.

What i have tried so far

  1. Use Multer's InMemory - same result
  2. Use Multer's dest attribute and piped the stream from fs to gridfs - same result.
  3. Use the gridfs-stream module - Same result
  4. Used the Native GridFS/GridStoire - Same result.

Any help will be very much appreciated.


回答1:


Now, what you missed here is that the "buffer" from the "inMemory" option is not "either/or" and does not mean that the content is held "In Memory" instead. It is in fact a "copy" of the data that is also sent to the temporary file on disk.

So it really doesn't matter if you set "inMemory" or not as the files will still be created ( by default in the /tmp directory ) but these will of course unlink when out of scope:

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

});

And of course a simple test:

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

Alternately call the middle-ware in-line with your request method, and/or set up the onFileUploadComplete() handler rather than iterate the content of req.files. The "gridfs=stream" package is probably the simplest option you have to upload content and trying to work from a buffer that is a copy is not really going to offer any real advantage since the IO cost and storage is always going to be there.



来源:https://stackoverflow.com/questions/28008731/unable-to-write-buffer-to-mongodb-gridfs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!