使用Sequelize保存图片

6
我正在使用Sequelize作为我的ORM,通过Postgres创建一个Node应用程序。但是Sequelize文档中缺少如何进行数据块(特别是图像)保存的任何说明。有没有人知道:

  1. 如何使用sequelize将图像保存到数据库中,例如来自表单。从我所了解的情况来看,似乎我需要将图像转换为二进制数据。
  2. 如何创建带有图像的种子,以便在我的应用程序上线之前进行测试。

这是一个示例模型的迁移文件

export default {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable('Users', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER,
      },
      firstName: {
        allowNull: false,
        type: Sequelize.STRING,
      },
      lastName: {
        type: Sequelize.STRING,
      },
      photo: { <--------------------------- Image
        type: Sequelize.BLOB,
      },
      email: {
        type: Sequelize.STRING,
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE,
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE,
      },
    });
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.dropTable('Users');
  },
};

除了一个小的种子文件外

export default {
  up: (queryInterface, Sequelize) => {
    /*
      Add altering commands here.
      Return a promise to correctly handle asynchronicity.

      Example:
      return queryInterface.bulkInsert('Persons', [{
        name: 'John Doe',
        isBetaMember: false
      }], {});
    */
    return queryInterface.bulkInsert('Users', [
      {
        firstName: 'Ricky',
        lastName: 'Sparks',
        // photo: <---------- what should I fill in here to seed with a photo file?
        email: 'email@gmail.com',
        createdAt: Sequelize.fn('NOW'),
        updatedAt: Sequelize.fn('NOW'),
      },
    ]);
  },

  down: (queryInterface, Sequelize) => {
    /*
      Add reverting commands here.
      Return a promise to correctly handle asynchronicity.

      Example:
      return queryInterface.bulkDelete('Persons', null, {});
    */

    return queryInterface.bulkDelete('Users', null, {});
  },
};
2个回答

7
您可以尝试使用Sequelize-file,让它处理文件存储、与模型的关联以及从 blob 读取的工作。除此之外,您还可以使用请求对象中的缓冲区、流来实现,通常情况下,这些模块会暴露出缓冲区或流等内容。

通常的流程如下:

在提交时:

  • 提交表单 -> http 请求对象 -> 读取缓冲区 -> 存储到 blob

在响应时:

  • 从 blob 中读取 -> 转换为缓冲区 -> 构建 http 响应。

关于测试,您可以手动创建一些文件,并附带一个 json 文件,其中包含正确的宽度、高度、图像类型等信息,然后使用这些文件进行读取和提交,或者通过某种方式模拟文件。

我个人会尽量避免将文件存储到数据库中,因为即使在理论上也很难且不易测试等等。相反,您可以将文件存储在文件系统中,使用编码后的文件名、存储信息在数据库中,检查存在等方式比进行所有这些操作更容易,除非有必要。


是的,我正在阅读关于不将文件存储在数据库中的内容。我想Postgres具有内置压缩和其他功能,这比保存在服务器文件系统上或自己构建更可取。对于v0产品来说,这是最合理的选择,因为最终要移动到CDN等,但我可能是错误的。 - Brandon
你可以随时对你的解决方案进行压力测试并获得一些性能反馈,HTTP响应中的压缩可以处理,PostgreSQL不能神奇地将100MB的图像压缩为10MB..这种方式的压缩有点无意义。 - Gntem

0
你可以尝试这个答案来回答问题1。
步骤1.声明图像保存模型
文件:models/imageModel.js
 import { DataTypes } from 'sequelize';

export default (sequelize) => {
  const imageModel = sequelize.define(
    'images',
    {
      id: {
        type: DataTypes.UUID,
        defaultValue: DataTypes.UUIDV4,
        allowNull: false,
        primaryKey: true,
      },
      image: { 
        type: DataTypes.BLOB('long'), // <- type for image ( database :postgresql )
        allowNull: true 
      },
    },
    { schema: 'imageSchema' },
  );
  return imageModel;
};

步骤2:model/index.js Sequelize连接

import { Sequelize, DataTypes } from 'sequelize';
import sequelize from '../db.config.js';
import imagesTable from './imageModel.js';

const db = {};

// create Schema if not Exist
// might crash the Node on first npm start if no Schema Exist, run again
(async () => {
  await sequelize.showAllSchemas({ logging: false }).then(async (data) => {
    if (!data.includes('imageSchema')) await sequelize.createSchema('imageSchema');
  });
})();

db.sequelize = sequelize;
db.Sequelize = Sequelize;

db.images = imagesTable(sequelize, DataTypes);

export default db;

步骤2: 使用jimp(^0.16.1)和file-type(^17.1.2)将图像转换为缓冲区,以读取图像元信息,[如果需要,使用npm安装jimp和file-type]

  const imagePath = `path/to/image`;
  const jimpImageToBuffer = await jimp
    .read(imagePath) // read image from path
    .then((ele) => {
      const mimeForImage = ele._originalMime;
      return ele.getBufferAsync(mimeForImage); // convert image to buffer(compatiable to save to database).
    })
    .catch((err) => console.log(err));
  console.log(jimpImageToBuffer); // <- image in buffer, save this file in database(in image column)
  const imageExtensionAndMIME = await fileTypeFromFile(imagePath); // extract image extension and image type.
  const { ext: imageExtension, mime: imageMimeType } = imageExtensionAndMIME; 

步骤三:在代码库中。

import db from "../models/index.js"

// save to database using sequelize
export const saveImagesToDatabse = async (imageDetails) => {
  const savedImages = await db.images.create(imageDetails);
  return savedImages;
};

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