Хранение потока данных из запроса POST в GridFS, express, mongoDB, node.js

Я пытаюсь понять, как я могу опубликовать изображение непосредственно в GridFS, не сохраняя его где-либо на сервере в качестве временного файла.

Я использую Postman (chrome ext.) для публикации файла, и мне удается сохранить это сообщение в виде файла, используя:

req.pipe(fs.createWriteStream('./test.png'));

Я также могу сохранять непосредственно в GridFS из readStream, когда readStream создается из файла на сервере. (см. код)

У меня есть следующие файлы: saveFromReq.js, который прослушивает POST и просто передает его в savePic.js.

saveFromReq.js:

var express = require('express');
var app = express();
var savePic = require('./savePic');
var fs = require('fs');
var GridStore = require('mongodb').GridStore;
var pic = './square.png';
var picID;



//When the following

 //var pic = fs.createReadStream('./square.png', {autoClose: true});

//is not commented out, and 'req' is replaced with 'pic' in the savePic function,
//the file square.png is stored correctly to GridFS

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

    savePic(req, function(id){});
    res.writeHead(200, {'Content-Type': 'text' });
    res.end("Sucsess!\n");

});

app.listen(process.env.PORT || 3413);

savePic.js:

var savePic = function(req, callback){


var Db = require('mongodb').Db,
    MongoClient = require('mongodb').MongoClient,
    Server = require('mongodb').Server,
    ReplSetServers = require('mongodb').ReplSetServers,
    ObjectID = require('mongodb').ObjectID,
    Binary = require('mongodb').Binary,
    GridStore = require('mongodb').GridStore,
    Grid = require('mongodb').Grid,
    Code = require('mongodb').Code,
    BSON = require('mongodb').pure().BSON,
    assert = require('assert');
    fs = require('fs');

    //When the following 

      //req.pipe(fs.createWriteStream('./test.png'));

    //is not commented out, the correct image is stored to test.png, and 
    //the sequence after req.on("data"... starts
    //(That sequence does not start at all when this is commented out..)

var fileId = new ObjectID();
var db = new Db('testDB', new Server('localhost', 27017));
// Establish connection to db
db.open(function(err, db) {


  var gridStore = new GridStore(db, 'test', 'w');

  //open 
  gridStore.open(function(err, gridStore) {
    console.log("opened");


    req.on("data", function (data) {
        console.log("data recieved");
            gridStore.write(data, function (err, gridStore) {
                if (err) {
                    console.log("error writing file");
                }
            });
        });
     req.on("end", function () {
            gridStore.close(function (err, gridStore) {
                if (!err) {
                    console.log("The file has been stored to database.");
                    db.close();
                }
            });
        });
           req.pipe(gridStore);


      });




});
callback(fileId);
};
module.exports = savePic;

Любая помощь будет принята с благодарностью!


person eirik    schedule 31.12.2013    source источник


Ответы (5)


gridfs-stream делает это довольно просто:

// `gfs` is a gridfs-stream instance
app.post('/picture', function(req, res) {
  req.pipe(gfs.createWriteStream({
    filename: 'test'
  }));
  res.send("Success!");
});
person robertklep    schedule 31.12.2013
comment
Спасибо, это работает. Кроме того, не могли бы вы рассказать, как обрабатывать «несколько типов файлов» или несколько элементов управления файлами в форме. и как получить исходное имя файла из поста. - person codin; 05.09.2014
comment
@robert, я новичок в gridfs. Не могли бы вы сказать мне, какое имя файла в createWriteStream. Что будет, если я захочу хранить байты? Должен ли я создать для него новый вопрос? - person JN_newbie; 23.03.2015
comment
@Java_NewBie имя файла задокументировано здесь. По сути, это (необязательный) идентификатор для документа GridFS, который вы создаете (поэтому вы можете получить доступ к этому документу не только через его уникальное свойство _id, но и через удобочитаемую строку). Вы можете сделать из этой строки что угодно. - person robertklep; 23.03.2015
comment
@robertklep Спасибо, Роберт. Я пытаюсь использовать приведенный выше код для хранения видео (байтов), которое будет отправлено с устройства в gridfs с вашим ответом. но я изо всех сил пытаюсь сохранить его. Мне нужно понимание. Я разместил вопрос в отдельной ветке, но кто-то перешел по этой ссылке как дубликат. Спасибо. - person JN_newbie; 23.03.2015
comment
@robertklep, как я могу получить информацию о файле, хранящемся в обратном вызове? Спасибо! - person vinesh; 12.12.2015
comment
@vinesh, ты имеешь в виду метаданные? См. это. - person robertklep; 12.12.2015
comment
@robertklep Да, я нашел метаданные для сохраненного файла. ваш ответ помог мне решить проблему. Спасибо :) - person vinesh; 12.12.2015

хотя ответ @robertklep правильный, я хотел бы добавить кое-что к его ответу. Этот код показывает, как вы можете отправить обратно метаданные сохраненного файла.

app.post('/picture', function(req, res) {
  req.pipe(gfs.createWriteStream({
    filename: 'test'
  }).on('close', function(savedFile){
    console.log('file saved', savedFile);
    return res.json({file: savedFile});
  }));
})  
person vinesh    schedule 12.12.2015

Это сработало для меня с мангустом:

 var gfs = Grid(mongoose.connection.db, mongoose.mongo);
    var writeStream = gfs.createWriteStream({
        filename: name,
        mode: 'w',
        content_type: 'video/mp4'
    });
    writeStream.on('close', function() {
        console.log('close event');
    });

    fs.createReadStream('uploads/' + name + '/' + name + '.mp4').pipe(writeStream);
    console.log('stream.write: ' + name + '/' + name + '.mp4');

Я борюсь пару дней с получением видео в браузере на стороне клиента. Это то, что я пробовал до сих пор:

var readstream = gfs.createReadStream({
        filename: file.filename
    });

    readstream.on('data', function(data) {
        res.write(data);
        console.log(data);
    });

    readstream.on('end', function() {
        res.end();        
    });

    readstream.on('error', function (err) {
        console.log('An error occurred!', err);
        throw err;
    });

Мои данные на стороне MongoDB выглядят так:

db.fs.chunks.find() { "_id": ObjectId("5757e76df14741bf0391aaca"), "files_id": ObjectId("5757e76df14741bf0391aac8"), "n": 0, "данные": BinData(0,"AAAAIGZ0eXBpc29.. ..

И тип содержимого - «видео/mp4»:

регистрация на стороне браузера печатает это:

Объект { 0: "�", 1: "�", 2: "�", 3: " ", 4: "f", 5: "t", 6: "y", 7: "p", 8 : "i", 9: "s", еще 85003… }

Может ли кто-нибудь спасти мою жизнь? Надеюсь, вы не сочтете мой пост неудобным в этом месте.

person udito    schedule 08.06.2016

Полный код для вставки txt-файла в mongodb с использованием gridfs в nodejs. Это работает хорошо `

var mongoose=require("mongoose");
var gridfsstream=require("gridfs-stream");
var fs=require("fs");
mongoose.connect("mongodb://localhost:27017/testimage");
var conn=mongoose.connection;
gridfsstream.mongo=mongoose.mongo;
conn.once("open",function()
{
    console.log("database connected successfully");
    var gfs=gridfsstream(conn.db);
    var writestream=gfs.createWriteStream({
        filename:"danger.txt"
    });
    fs.createReadStream("sivakasi.txt").pipe(writestream);
    writestream.on("close",function(file)
    {
        console.log(file.filename +"stored successfully into mongodb using gridfs");
    });
    writestream.on("error",function(file)
    {
        console.log(file.filename +"not stored into mongodb using gridfs");
    });
});
conn.on("error",function()
{
    console.log("database not connected try again!!!");
});

`

person vigneshRavi    schedule 07.01.2017

полный код для публикации изображения из html в nodejs, сохраните это изображение в mongodb с помощью системы gridfs и отобразите это изображение на сервере. Этот код работает хорошо.

var express=require("express");
var bodyparser=require("body-parser");
var multer=require("multer");
var app=express();
var upload = multer({ dest: '/tmp/'});
app.use(bodyparser.urlencoded({extended:false}));
app.post("/uploadimage",upload.single("file"),function(request,response)
{
    var mongoose=require("mongoose");
    var gridfsstream=require("gridfs-stream");
    var fs=require("fs");
    mongoose.connect("mongodb://localhost:27017/testimage");
    var con=mongoose.connection;
    gridfsstream.mongo=mongoose.mongo;
    con.once("open",function()
    {
        console.log("test image database connected successfully");
        var gfs=gridfsstream(con.db);
        var readstream=fs.createReadStream(request.file.originalname);
        var writestream=gfs.createWriteStream({
            filename:"mentorpicthree.jpg"
        });
        readstream.pipe(writestream);
        writestream.on("close",function()
        {
            console.log("image stored in mongodb database successfully");
            fs.readFile(request.file.originalname,function(err,data)
            {
                if(err)
                {
                    response.writeHead(404,{"Content-Type":"text/plain"});
                    console.log("error");

                }
                else
                {
                        response.writeHead(200,{"Content-Type":"image/jpg"});
                        response.end(data);
                }
            });
        });
        writestream.on("error",function()
        {
            console.log("image not stored in mongodb database");
        });

    });
    con.on("error",function()
    {
        console.log("database not connected try again!!!");
    });

});
app.listen(8086,function()
{
    console.log("server running on port 8086");
});
<html>
<head>
    <title>FILE UPLOAD</title>
</head>
<body>
<p>Ryan Dhal</p>
<form action="http://127.0.0.1:8086/uploadimage" method="POST" enctype="multipart/form-data">
    <input type="file" name="file">
    <br>
    <input type="submit" value="UPLOAD">
</form>
</body>
</html>

person vigneshRavi    schedule 07.01.2017