Blob 不是 Blob - 如何在 firestore Blob 中存储 canvas.toBlob?

Blob not Blob - how to store a canvas.toBlob in a firestore Blob?

我有一个Javascript native Blob of a jpeg and I'd like to store it as a firestore blob

但是 Firestore 当然会说“FirebaseError:函数 DocumentReference.update() 调用时使用了无效数据。不支持的字段值:自定义 Blob 对象(在文档中的字段图像中找到...”

有什么方法可以从 javascript-blob 转换为 firestore-blob?

canvas.toBlob(async (blob)=> {
    console.info(`Converting to blob: ${blob.constructor.name} and storing to firestore...`);
    await myselfRef.update({
        image: blob
    }, 'image/jpeg', 0.4));

要将 JavaScript Blob 转换为 Firestore Blob,您必须按照以下步骤操作:

  1. 使用 your_blob.arrayBuffer().
  2. 将 JavaScript Blob 转换为 ArrayBuffer
  3. 通过将您刚刚进入的 ArrayBuffer 作为单个参数传递给 the constructor.
  4. 将其包装到 Uint8Array 中
  5. 最后,使用 firebase.firestore.Blob.fromUint8Array(your_array) 方法创建 Firestore Blob。

如果你想执行逆向转换,从 Firestore Blob 到 JavaScript Blob,你几乎必须做相反的事情:

  1. 使用 firestore_blob.toUint8Array().
  2. 将 Firestore Blob 转换为 Uint8Array
  3. 使用数组 the constructor 创建 JavaScript Blob。请记住,您必须使用数组列表调用它,例如 new Blob([my_array]).

这是实践中的一个例子。函数 save() 用于将 canvas 的内容保存到 Firestore。并且,函数 load() 再次将它们加载到 canvas 中。

const canvas = document.querySelector('canvas');
const context = canvas.getContext('2d');
const db = firebase.firestore();

function save() {
  canvas.toBlob(async blob => {
    const blob_url = URL.createObjectURL(blob);
    const ref = db.collection('blob').doc('blob');
    const array_buffer = await blob.arrayBuffer();
    const uint8_array = new Uint8Array(array_buffer);
    const firebase_blob = firebase.firestore.Blob.fromUint8Array(uint8_array);
    ref.update({
      image: firebase_blob,
    });
  });
}

async function load() {
  const ref = db.collection('blob').doc('blob');
  const doc = await ref.get();
  const firebase_blob = doc.get('image');
  const uint8_array = firebase_blob.toUint8Array();
  const blob = new Blob([uint8_array]);
  const blob_url = URL.createObjectURL(blob);
  const image = new Image();
  image.onload = () => {
    context.clearRect(0, 0, canvas.width, canvas.height);
    context.drawImage(image, 0, 0);
    URL.revokeObjectURL(blob_url);
  }
  image.src = blob_url;
}