Open4

WebKitBlobResourceエラー1

ムギュウムギュウ

SafariのindexedDBにBlob入れると、「エラー1」が出ることがある

「エラー1」だけでは原因を特定しにくいが、私の事例では以下の条件でエラーが発生した

  • indexedDBからBlobを読み込む
  • URL.createObjectURLで、BlobからobjectURLを生成する
  • indexedDBに再度同じBlobを書き込むと「エラー1」になる
ムギュウムギュウ

対処方法 BlobをcloneしてからindexedDBへ書き込む
FileReaderでデータ実体を読み直してcloneする

  // WebKitBlobResourceエラー1対策
  const clonedBlob = await new Promise<Blob>((resolve, reject) => {
    const fileReader = new FileReader();
    fileReader.onload = () => {
      if (!(fileReader.result instanceof ArrayBuffer)) {
        reject(new Error("Failed to read blob"));
        return;
      }

      resolve(new Blob([fileReader.result], { type: blob.type }));
    };
    fileReader.onerror = () => {
      reject(fileReader.error);
    };
    fileReader.readAsArrayBuffer(blob);
  });

個人開発アプリがSafariでもまともに動くようになった
https://almap.hata6502.com/

パフォーマンスに影響ありそうな方法だが、
indexedDBの読み込みより書き込みのほうが頻度が低いため、問題は起きなさそう

ムギュウムギュウ

パフォーマンスの問題が生じた方法
indexedDBに直接Blob入れず、MIME typeとArrayBufferに分解してDBに入れる

DB読み込みが大幅に遅くなってしまった
画像を500枚くらいindexedDBに入れると、Android端末で全部読み込むまでに1分くらいかかってしまった

indexedDBのデータ構造を変えてマイグレーションする必要もあり、大掛かりになりやすい

ムギュウムギュウ

うまくいかなかった方法
blob.slice()structuredClone(blob)でBlobをcloneする

    const albumPutRequest = almapDB
      .transaction(["album"], "readwrite")
      .objectStore("album")
      .put({
        ...photo,
        blob: blob.slice(),
      });

結局「エラー1」が出るままだった
データ実体はcloneされず、あくまでBlob Objectがcloneされるらしい