【问题标题】:Re-create an image from binary in Node.js and Mongoose在 Node.js 和 Mongoose 中从二进制文件重新创建图像
【发布时间】:2020-08-30 20:32:51
【问题描述】:

我正致力于在 Node.js 中创建上传/下载图像功能。到目前为止,有一个 POST 请求将图像保存为 MongoDB 中的二进制文件,还有一个 GET 请求返回该图像。但我不知道如何使用该响应,它是一个数字数组,不知道如何转换它。

这是 Mongo 模型:

image.js const mongoose = require('mongoose'); const Schema = mongoose.Schema;

const ImageItem = new Schema({
  id: {
    type: String
  },
  value: {
    type: Buffer
  },
});

module.exports = Image = mongoose.model('image', ImageItem);

POST 图像在 DB 中创建条目:

const image = require('../models/image');
const user = require('../models/user');

const multer = require('multer');
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, './uploads/');
  },
  filename: function (req, file, cb) {
    cb(null, file.originalname + new Date().toISOString());
  },
});


const upload = multer({
  storage: storage,
});

module.exports = function (app) {
  app.post('/upload', upload.single('value'), (req, res, next) => {
    const newImage = new image({
      id: req.body.id,
      value: req.file.path,
    });
    newImage
      .save()
      .then((result) => {
        console.log(result);
        res.status(201).json({
          message: 'created succesfully',
        });
      })
      .catch((err) => {
        console.log(err);
        res.status(500).json({
          error: err,
        });
      });
  });
};

以及在 DB 中创建的条目:

为了获取图像,我创建了一个 GET 请求:

const image = require('../models/image');

module.exports = function (app) {
  app.get('/upload/:id', (req, res) => {
    console.log('req.body.id', req.params);
    image.find({ id: req.params.id }, function (err, results) {
      if (err) {
        res.send(`error: ${err}`);
      } else {
        res.send(results);
      }
    });
  });
};

在 Postman 中测试会返回一个包含数字数组的 JSON:

[
    {
        "_id": "5ebd1c112892f4230d2d4ab4",
        "id": "email123@test.com",
        "value": {
            "type": "Buffer",
            "data": [
                117,
                112,
                108,
                111,
                97,
                100,
                115,
                47,
                117,
                115,
                101,
                114,
                80,
                105,
                99,
                116,
                117,
                114,
                101,
                46,
                112,
                110,
                103,
                50,
                48,
                50,
                48,
                45,
                48,
                53,
                45,
                49,
                52,
                84,
                49,
                48,
                58,
                50,
                51,
                58,
                49,
                51,
                46,
                57,
                51,
                52,
                90
            ]
        },
        "__v": 0
    }
]

如何使用这些数据来获取实际图像?

【问题讨论】:

    标签: javascript node.js mongodb rest mongoose


    【解决方案1】:

    您可以从该数组创建Buffer

    const imageBuffer = Buffer.from(row.value.data); // [117, 112, 108...]
    

    无论如何检查您的ImageItem 架构,row.value 将是Buffer

    现在您需要做的就是设置正确的 content-type 并使用 res.send 响应 Buffer 而不是 Mongoose 架构。

    app.get('/upload/:id', (req, res) => {
        console.log('req.body.id', req.params);
        image.find({ id: req.params.id }, function (err, results) {
          if (err) {
            res.send(`error: ${err}`);
          } else {
            const [row] = results;
            res.header('Content-Type', 'image/png');
            res.send(row.value);
          }
        });
    });
    

    如果您不知道Content-Type,可以使用file-type 包从Buffer 获取它。

    const { mime } = fileType(row.value)
    

    由于您只获取特定图像,您可能希望使用.findOne 而不是.find


    现在您还有其他问题,您存储的是文件路径,而不是您想要的二进制图像。

    您发布的那些字节等于:uploads/userPicture.png2020-05-14T10:23:13.934Z"

    const data = new TextDecoder().decode(new Uint8Array([117,112,108,111,97,100,115,47,117,115,101,114,80,105,99,116,117,114,101,46,112,110,103,50,48,50,48,45,48,53,45,49,52,84,49,48,58,50,51,58,49,51,46,57,51,52]))
    
    console.log(data);

    您必须保存实际图像,而不是您的代码工作的文件路径。

    const fs = require('fs').promises;
    // ....
    
    const newImage = new image({
          id: req.body.id,
          value: await fs.readFile(req.file.path)
    });
    

    【讨论】:

    • 第一行的const image应该放在哪里?
    • 将其重命名为 imageBuffer 以避免冲突。正如您在第二个 sn-p 上看到的那样,它被放置在路线上。
    • 首先感谢您的回复,但目前无法正常工作。我输入了该代码,并在 Postman 中返回此错误消息:Proxy error: Could not proxy request /upload/email122345@test.com from localhost:3000 to http://localhost:5000 (ECONNRESET).。我正在使用 nodemon 从客户端和服务器运行我的应用程序。尝试获取图像后,服务器崩溃:TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received undefined
    • 在客户端它说:Proxy error: Could not proxy request /upload/email122345@test.com from localhost:3000 to http://localhost:5000. See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ECONNRESET).我在服务器上使用 5000,在客户端使用 3000
    • 那么你没有将数组传递给BUffer.from
    【解决方案2】:

    当您将图像发送到客户端时,mongoose 会调用“toJSON”方法,默认情况下,Buffer JSON 对象看起来就像您展示的那样。您可以覆盖猫鼬方案的 toJSON 方法(在这里您可以找到信息 - https://mongoosejs.com/docs/guide.html#toJSON),您的服务器将返回您的图像的 base64 表示。

    const mongoose = require("mongoose"),
      Schema = mongoose.Schema;
    
    var imageSchema = new Schema({
      data: {
        type: Buffer,
        required: true,
      },
      type: {
        type: String,
        required: true,
      },
    });
    
    imageSchema.set("toJSON", {
      virtuals: true,
      versionKey: false,
      transform: function (doc, ret) {
        const base64 = doc.data.toString("base64");
        ret.data = `data:image${doc.type};base64,${base64}`;
    
        return ret;
      },
    });
    
    module.exports = mongoose.model("Image", imageSchema);

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多