使用Node.js/Express和Mongoose将图片存储在MongoDB中

30

目前我使用angular-file-upload来处理图片上传,我只是将图片保存到服务器的文件系统中并在HTML中引用它。然而,我想尝试直接将图像存储在我为我的博客文章定义的模式中的数据库中。

var blogSchema = new Schema({
    title: String,
    author: String,
    body: String,
    likes: { type: Number, default: 0 },
    comments: [{ type: Schema.Types.ObjectId, ref: 'Comment' }],
    date: { type: Date, default: Date.now },
    imageURL: String   // instead of this

    image: // store it directly
});

"imageURL: String" stores the path to the image.
我希望能够只有一个字段来存储图像本身。我在想,我可以像以前一样上传图像,但是上传后将图像转换为二进制(或其他形式),然后将其存储在Mongo中。这种做法可行吗?
感谢!
3个回答

34

以下示例展示了如何使用mongoose将图像上传到MongoDB。点击此链接查看原始来源

var express = require('express');
var fs = require('fs');
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var imgPath = '/path/yourimage.png';

mongoose.connect('localhost', 'testing_storeImg');

var schema = new Schema({
    img: { data: Buffer, contentType: String }
});

var A = mongoose.model('A', schema);

mongoose.connection.on('open', function () {
  console.error('mongo is open');

  A.remove(function (err) {
    if (err) throw err;

    console.error('removed old docs');

    // store an img in binary in mongo
    var a = new A;
    a.img.data = fs.readFileSync(imgPath);
    a.img.contentType = 'image/png';
    a.save(function (err, a) {
      if (err) throw err;

      console.error('saved img to mongo');

      // start a demo server
      var server = express.createServer();
      server.get('/', function (req, res, next) {
        A.findById(a, function (err, doc) {
          if (err) return next(err);
          res.contentType(doc.img.contentType);
          res.send(doc.img.data);
        });
      });

      server.on('close', function () {
        console.error('dropping db');
        mongoose.connection.db.dropDatabase(function () {
          console.error('closing db connection');
          mongoose.connection.close();
        });
      });

      server.listen(3333, function (err) {
        var address = server.address();
        console.error('server listening on http://%s:%d', address.address, address.port);
        console.error('press CTRL+C to exit');
      });

      process.on('SIGINT', function () {
        server.close();
      });
    });
  });

});

4
谢谢你的回答!我已经能够使用它将文件保存到数据库中了。你知道怎样在客户端使用Angular加载图片吗? - Bryan Cho
@Jaco 在从文件管理器中选择图像后如何自动获取图像路径? - ridoansaleh
@BryanCho 你可以使用 fromCharCode & btoa 对从文档中提取的数据进行编码,然后将其分配给图像的源。例如, src = "data:image/png;base64," + btoa(String.fromCharCode.apply(null, img.data)) - David Streid

0
router.get("/:i", function (req, res) {
    
   var dataGet = {_id: req.params.i}
    
   fileModel.findOne(dataGet).exec(function (err, doc) {

        if (err) {
            return next(err)
        }
    
        var base64dataa = new Buffer(doc.fileData,'binary').toString('base64');
    
        var ress = {
           fileData: base64dataa,
           mime: doc.mimeType,
           name: doc.fileName
        }

       // res.json(ress)
       res.contentType('image/jpeg')
       res.send(doc.fileData)
   })
})  
        
    
    
router.post('/display/', function (req, res) {

       var data = {
           file: req.body.fileData,
           mime: req.body.mime,
           name: req.body.name
       }
    
       res.json(data)
})

4
你能解释一下你的解决方案是如何避免删除的吗? - Web_Designer

0
这是将数据保存到mongodb的代码。 data是二进制的。我可以显示这个'image/jpg,base64,{{data}}',但我不知道如何显示base64data

file.on('data', function (data) {
            buffer += data;

            var file = new fileModel({
                fileData: data
            })

var Busboy = require('busboy');

router.post('/upload', function (req, res) {

    var busboy = new Busboy({headers: req.headers});
    var base64data = "";
    var filetype = "";
    var name = "";
    var argum = [];
    var data2

    busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {

        var buffer = "";
        filetype = mimetype;
        name = filename;


        // file.setEncoding('base64');


        file.on('data', function (data) {
            buffer += data;

            var file = new fileModel({
                fileData: data
            })
            //
            file.save(function (err, file) {
                if (err) {
                    return next(err)
                }
                // res.json(201, newData)
                // console.log("Save in database" + file.desc)
            })
        });
        file.on('end', function () {
            base64data = buffer;
        });
    });


    busboy.on('field', function (fieldname, val, fieldnameTruncated, valTruncated) {

        argum.push(val);
    });
    busboy.on('finish', function () {
        var base64dataa = new Buffer(base64data, 'binary').toString('base64');
        res.json(base64dataa)
        var jsonBin = {
            base64data_: base64data, mime_: filetype, name_: name,
            owner_: argum[0], description_: argum[1]
        }

        // res.json(jsonBin)

        var file = new fileModel({
            fileData: jsonBin.base64data,
            mimeType: jsonBin.mime_,
            fileName: jsonBin.name_,
            fileOwner: jsonBin.owner_,
            desc: jsonBin.description_
        })
        //
        file.save(function (err, file) {
            if (err) {
                return next(err)
            }
            // res.json(201, newData)
            console.log("Save in database" + file.desc)
        })
    });

    req.pipe(busboy);
});


"I can this display 'image/jpg,base64,{{data}}' but I don't understand how can I display base64data" 这句话缺少一个动词,我猜测。如果我猜对了,请添加它。 - YakovL
数据是具有二进制数据的变量。我可以将其显示为'image/jpg,base64',但是base64数据与数据不同。我甚至无法显示它。 - Krzysztof Sikora

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接