我应该使用哪种数据类型在MongoDB中存储图像? [英] What data type should I use to store an image with MongoDB?

查看:89
本文介绍了我应该使用哪种数据类型在MongoDB中存储图像?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有base64的图像,例如

I have an image with base64, e.g.

data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAAQABAAD/7QCcUGhvdG9zaG9w....

如何保存在数据库中?模式中字段的类型应该是什么?缓冲区?

How to save in the database? What should be the type of the field in schema? Buffer?

推荐答案

简短的答案存储为,在猫鼬模式中,您可以使用Buffer进行此操作.

The short answer is store as "Binary", for which in a mongoose schema you can use Buffer to do this.

更长的形式是演示转换的往返,该转换从原始二进制文件开始,然后再返回.在大多数现实情况下,Base64编码/解码不是必需的步骤,而仅用于演示:

The longer form is to demonstrate a round trip of conversion starting with the original binary and back again. Base64 encoding/decoding is not a necessary step in most real world cases, and is just there for demonstration:

  • 从文件中读取图像(或任何二进制数据)
  • Base64对该数据进行编码(只是为了证明它可以完成)-可选
  • 从Base64中转回二进制数据(仅表明它可以完成)-可选
  • 在数据库中存储二进制数据
  • 从数据库读取二进制数据
  • 将二进制数据输出到新文件
  • Read an image (or any binary data) from file
  • Base64 encode that data (just to show it can be done) - optional
  • Turn back into Binary data from Base64 ( just to show it can be done ) - optional
  • Store Binary data in the database
  • Read Binary data from the database
  • Output binary data to a new file

因此,架构部分很简单,只需使用Buffer:

So the Schema Part is simple, just use Buffer:

var albumSchema = new Schema({
  name: String,
  image: Buffer
})

然后,我们要做的就是遵循该过程,将二进制数据放入属性中,然后再次读出来.

Then all we are going to do is follow the process and put the binary data into the property and read it back out again.

请注意,如果您直接来自带有MIME类型的字符串,例如:

Note though that if you are coming directly from a string with a MIME type on it like :

  data:image/png;base64,long-String

只需使用JavaScript .split(),并为base64字符串本身获取第二个数组索引:

Just use a JavaScript .split() and take the second array index for the base64 string itself:

var string = "data:image/png;base64,long-String"
var bindata = new Buffer(string.split(",")[1],"base64");

以下是带有完整演示内容的清单:

Here's a listing with a complete demo in and out:

const async = require('async'),
      mongoose = require('mongoose'),
      Schema = mongoose.Schema,
      fs = require('fs');

mongoose.Promise = global.Promise;
mongoose.set('debug',true);
mongoose.connect('mongodb://localhost/test');

var albumSchema = new Schema({
  name: String,
  image: Buffer
})

const Album = mongoose.model('Albumn', albumSchema);


async.series(
  [
    (callback) =>
      async.each(mongoose.models,(model,callback) =>
        model.remove({},callback),callback),

    (callback) =>
      async.waterfall(
        [
          (callback) => fs.readFile('./burger.png', callback),

          (data,callback) => {
            // Convert to Base64 and print out a bit to show it's a string
            let base64 = data.toString('base64');
            console.log(base64.substr(0,200));

            // Feed out string to a buffer and then put it in the database
            let burger = new Buffer(base64, 'base64');
            Album.create({
              "title": "burger",
              "image": burger
            },callback)
          },

          // Get from the database
          (album,callback) => Album.findOne().exec(callback),

          // Show the data record and write out to a new file.
          (album, callback) => {
            console.log(album);
            fs.writeFile('./output.png', album.image, callback)
          }

        ],
        callback
      )


  ],
  (err) => {
    if (err) throw err;
    mongoose.disconnect();
  }
)

注意该示例最初是通过 asyncJS 和较旧的猫鼬给出的API,特别是具有不同的连接选项,如更现代和最新的API示例中所示.请参考这些,以在当前的NodeJS LTS版本上进行测试:

NOTE The example was originally given with asyncJS and older mongoose API, which notably has different connection options as shown in more modern and current API examples. Refer to these instead for testing on current NodeJS LTS releases:

或者使用更现代的语法和API进行比较:

Or with a a bit more modern syntax and API usage for comparison:

const fs = require('mz/fs');
const { Schema } = mongoose = require('mongoose');

const uri = 'mongodb://localhost:27017/test';
const opts = { useNewUrlParser: true };

mongoose.Promise = global.Promise;
mongoose.set('debug', true);
mongoose.set('useFindAndModify', false);
mongoose.set('useCreateIndex', true);

const albumSchema = new Schema({
  name: String,
  image: Buffer
});

const Album = mongoose.model('Album', albumSchema);

(async function() {

  try {

    const conn = await mongoose.connect(uri, opts);

    await Promise.all(
      Object.entries(conn.models).map(([k, m]) => m.deleteMany())
    )

    let data = await fs.readFile('./burger.png');

    // Convert to Base64 and print out a bit to show it's a string
    let base64 = data.toString('base64');
    console.log(base64.substr(0,200));

    // Feed out string to a buffer and then put it in the database
    let burger = new Buffer(base64, 'base64');
    await Album.create({ "title": "burger", "image": burger });

    // Get from the database
    // - for demo, we could have just used the return from the create() instead
    let album =  Album.findOne();

    // Show the data record and write out to a new file.
    console.log(album);
    await fs.writeFile('./output.png', album.image)


  } catch(e) {
    console.error(e);
  } finally {
    mongoose.disconnect()
  }

})()

甚至使用普通承诺",这是首选,或者您仍在使用不支持async/await的NodeJS.但是您不应该真的不应该,因为v6.x将于2019年4月终止使用 :

And even with "plain promises" where that is either preferred or you are still using a NodeJS without async/await support. But you really should not be, considering v6.x reaches end of life in April 2019:

// comments stripped - refer above
const fs = require('mz/fs');
const { Schema } = mongoose = require('mongoose');

const uri = 'mongodb://localhost:27017/test';
const opts = { useNewUrlParser: true };

mongoose.Promise = global.Promise;
mongoose.set('debug', true);
mongoose.set('useFindAndModify', false);
mongoose.set('useCreateIndex', true);

const albumSchema = new Schema({
  name: String,
  image: Buffer
});

mongoose.connect(uri, opts)
  .then(conn =>
    Promise.all(
      Object.entries(conn.models).map(([k, m]) => m.deleteMany())
    )
  )
  .then(() => fs.readFile('./burger.png'))
  .then(data => {
    let base64 = data.toString('base64');
    console.log(base64.substr(0,200));
    let burger = new Buffer(base64, 'base64');
    return Album.create({ "title": "burger", "image": burger });
  })
  .then(() => Album.findOne() )
  .then(album => {
    console.log(album);
    return fs.writeFile('./output.png', album.image)
  })
  .catch(console.error)
  .then(() => mongoose.disconnect());

这是一个 burger.png 可以玩:

也对如何减小Stack Overflow上的图像大小表示敬意,这使得此处的示例图像不会显示为原来是巨大",但仍以完整尺寸下载.

Also kudos to How to reduce image size on Stack Overflow which allows the sample image here to not appear as "huge" as it originally was, and yet still download at full size.

这篇关于我应该使用哪种数据类型在MongoDB中存储图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆