首页 > 解决方案 > 如何在存储在数据库中的 vue.js 中呈现 blob 图像

问题描述

我在前端使用 Vue.js。我在后端有 Node.js、Express、PostgreSQL(带有Sequelize)。

我在数据库中存储了一个包含缩略图的项目。

数据库模型

const Item = sequelize.define('item', {
    id: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        autoIncrement: true
    },
    name: {
        type: Sequelize.TEXT,
        allowNull: false,
    },

    image: {
        type: Sequelize.BLOB('long'),
        allowNull: true,
    },

就数据库而言,图像被存储为 Blob,我认为这很好(是的,我知道将图像放入数据库不是最佳实践)。

我在浏览器中观察到,我在 Vue 模板中访问this.item.image的对象是一个 Object 类型Buffer

控制台显示这是一个 Buffer 类型的对象

添加到数据库

我在我的 vue 模板中将项目添加到浏览器中的数据库中:

     <label for="image" class="itemCreate__field itemCreate__field--image">
       <span class="itemCreate__fieldLabel">Image</span>
       <input id="file"  type="file" accept="image/*" @change="onFileChange"/>
        <img v-if="itemPreviewImage" :src="itemPreviewImage" />
     </label>

该 HTML 依赖于这些方法:

     onFileChange(evt) {
        const files = evt.target.files || evt.dataTransfer.files;
        if (!files.length) return;
        this.createImage(files[0]);

    },
    createImage(file) {
        const image = new Image();
        const reader = new FileReader();

        reader.onload = evt => {
            this.itemPreviewImage = evt.target.result;
            this.item.image = evt.target.result;
        }

        reader.readAsDataURL(file);
    },

我在渲染图像的 vue 模板中有这个:

        <div v-if="item.image">
            <img :src="imgUrl" alt="Picture of item"/>
        </div>

从数据库渲染

我尝试了以下方法,但不起作用:

createObjectUrl从这里借来的:

    imgUrl(){
      const objUrl = window.URL.createObjectURL(new Blob(this.item.image.data));

      return objUrl;
    }

创建从这里借来的 base64 字符串:

    imgUrl(){
        const intArray = new Uint8Array(this.item.image.data);
        const reducedArray = intArray.reduce((data, byte) => data + String.fromCharCode(byte), '');

        const base64String = `data:image/png;base64, ${btoa(reducedArray)}`;


        return base64String;
    }

创建一个新Uint8Array的然后获取一个 objectUrl(在此处借用):

imgUrl(){
  const arrayBuffer = new Uint8Array(this.item.image);
  const blob  = new Blob([arrayBuffer], {type: "image/png"});

  return window.URL.createObjectURL(blob);

}

在所有情况下(包括一些使用 FileReader 的尝试),我都会得到损坏的图像。不过,我没有在控制台中收到错误。

认为问题在于我没有向数据库提交正确的数据。

我正在发送一个将文件附加为属性的 Ajax 请求,我可能应该将其转换为 ¿ 其他东西?

标签: javascriptpostgresqlvue.jsblobsequelize.js

解决方案


首先,确保你得到一个有效的base64字符串:https ://codebeautify.org/base64-to-image-converter

然后尝试为Item模型定义一个吸气剂

const Item = sequelize.define('item', {
    ...
    image: {
        type: Sequelize.BLOB('long'),
        allowNull: true,
        get () { // define a getter
            const data = this.getDataValue('image')
            return data ? data.toString('base64') : ''
        },
        set(val) {
          this.setDataValue('image', val);
        }
    },
    ...
}

计算属性

imgURL () {
    return this.item.image
        ? 'data:image/png;charset=utf-8;base64,' + this.item.image 
        : '' // some default image

}

推荐阅读