Невозможно записать буфер в MongoDB GridFS
Привет, ребята, я провел почти день, пытаясь выяснить это. Я использую флаг Multer inMemory для загрузки изображения с моей веб-страницы. Очевидная попытка - записать буфер, полученный от multer, в GridFs (более конкретно GridStore).
вот мой код Multer
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);
})
})
});
}
откуда мой объект БД? я просто добавляю его к объекту мангуст во время инициализации. Вот как выглядит код
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;
Так что в данный момент это происходит после того, как я бесчисленное количество раз менял код и достигал того же результата - без записи, без ошибок
Я получаю это каждый раз, хотя из выходного журнала мангуст
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, я возвращаю поток обратно правильно, но тогда запись никогда не происходит, и никакая ошибка не выдается.
Что я пробовал до сих пор
- Используйте Multer's InMemory - тот же результат
- Используйте атрибут Multer dest и передайте поток из fs в gridfs - тот же результат.
- Используйте модуль gridfs-stream - тот же результат
- Использовал Native GridFS/GridStoire - тот же результат.
Любая помощь будет очень ценится.
1 ответ
Теперь, что вы пропустили, так это то, что "буфер" из опции "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", вероятно, является наиболее простым вариантом загрузки контента, и попытка работать из буфера, являющегося копией, на самом деле не дает никаких реальных преимуществ, поскольку затраты на ввод-вывод и хранение всегда будут там.