fix: chunked base64 encode/decode for large image blobs in sync

This commit is contained in:
beo3000 2026-02-21 19:44:03 +01:00
parent 58c990d4e6
commit 364c99381c
2 changed files with 14 additions and 8 deletions

View File

@ -1 +1 @@
1.0.12
1.0.13

View File

@ -41,9 +41,7 @@ async function pullAndMerge(since: Date | null): Promise<string> {
if (!res.ok) throw new Error(`Pull failed: ${res.status}`);
const data: SyncPullResponse = await res.json();
const { contexts, topics, historyEntries, ratings } = data.changes;
const { imageBlobs } = data.changes;
const { contexts, topics, historyEntries, ratings, imageBlobs } = data.changes;
await db.transaction('rw', [db.contexts, db.topics, db.historyEntries, db.ratings, db.imageBlobs], async () => {
for (const serverCtx of contexts) {
@ -73,8 +71,10 @@ async function pullAndMerge(since: Date | null): Promise<string> {
for (const serverBlob of (imageBlobs ?? [])) {
const local = await db.imageBlobs.get(serverBlob.id);
if (!local || serverBlob.version > local.version) {
// Decode base64 → Blob
const bytes = Uint8Array.from(atob(serverBlob.data), (c) => c.charCodeAt(0));
// Decode base64 → Blob (chunked to avoid stack overflow on large blobs)
const binary = atob(serverBlob.data);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
const blobData = new Blob([bytes], { type: serverBlob.mimeType });
await db.imageBlobs.put({
id: serverBlob.id,
@ -102,11 +102,17 @@ async function pushAll(): Promise<void> {
db.imageBlobs.toArray(),
]);
// Encode Blob → base64 for transport
// Encode Blob → base64 for transport (chunked to avoid stack overflow on large blobs)
const imageBlobs = await Promise.all(
localBlobs.map(async (b) => {
const buf = await b.data.arrayBuffer();
const base64 = btoa(String.fromCharCode(...new Uint8Array(buf)));
const bytes = new Uint8Array(buf);
let binary = '';
const CHUNK = 8192;
for (let i = 0; i < bytes.length; i += CHUNK) {
binary += String.fromCharCode(...bytes.subarray(i, i + CHUNK));
}
const base64 = btoa(binary);
return {
id: b.id,
mimeType: b.mimeType,