Imansible scrivere il buffer in MongoDB GridFS

Ciao ragazzi ho passato quasi un giorno a cercare di capire questo. Sto usando la flag inMemory di multer per caricare un’immagine dalla mia pagina web. L’ovvio tentativo è di scrivere il buffer ricevuto da multer su GridFs (GridStore in modo più specifico).

ecco il mio codice multer

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

da dove viene il mio object DB? lo sto solo aggiungendo all’object mangusta durante l’inizializzazione. questo è come appare il codice

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; 

Quindi, al momento, sono in grado di cambiare il mio codice innumerevoli volte e di ottenere lo stesso risultato: nessuna scrittura, nessun errore

Lo capisco sempre dal registro di output di mangusta

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

Correggimi se sbaglio, ma perché sta facendo una ricerca quando sto “inserendo / scrivendo” in GridFS. Finora ottengo questo risultato e i miei punti di interruzione arrivano solo fino alla chiamata a GridStore.open, ritorno lo stream correttamente ma poi la scrittura non avviene mai e non viene generato alcun errore.

Quello che ho provato finora

  1. Usa InMemory di Multer – stesso risultato
  2. Usa l’attributo dest di Multer e convoglia il stream da fs a gridfs – stesso risultato.
  3. Usa il modulo gridfs-stream – Lo stesso risultato
  4. Usato il Native GridFS / GridStoire – Lo stesso risultato.

Qualsiasi aiuto sarà molto apprezzato.

Ora, quello che vi siete persi qui è che il “buffer” dall’opzione “inMemory” non è “uno / o” e non significa che il contenuto è trattenuto “In memoria”. È infatti una “copia” dei dati che viene anche inviata al file temporaneo su disco.

Quindi non importa se si imposta “inMemory” o non come i file verranno comunque creati (per impostazione predefinita nella /tmp ), ma questi ovviamente si scollegano quando vengono fuori ambito:

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

E ovviamente un semplice 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); }); 

In alternativa, chiamare middleware in linea con il metodo di richiesta e / o impostare il gestore onFileUploadComplete() piuttosto che iterare il contenuto di req.files . Il pacchetto “gridfs = stream” è probabilmente l’opzione più semplice per caricare i contenuti e provare a lavorare da un buffer che è una copia che non offrirà davvero alcun vantaggio reale dal momento che il costo dell’IO e lo spazio di archiviazione saranno sempre disponibili.