Как сделать изображение блоба в vue.js, хранящемся в базе данных - PullRequest
0 голосов
/ 03 мая 2018

Я использую 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, является объектом типа Buffer.

Console shows this is an Object with type 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-запрос с прикрепленным файлом в качестве свойства, и мне, вероятно, следует преобразовать его в ¿что-то еще?

1 Ответ

0 голосов
/ 03 мая 2018

Во-первых, убедитесь, что вы получаете действительную строку 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

}
...