fix: chunked base64 encode/decode for large image blobs in sync
This commit is contained in:
parent
58c990d4e6
commit
364c99381c
|
|
@ -1 +1 @@
|
||||||
1.0.12
|
1.0.13
|
||||||
|
|
@ -41,9 +41,7 @@ async function pullAndMerge(since: Date | null): Promise<string> {
|
||||||
if (!res.ok) throw new Error(`Pull failed: ${res.status}`);
|
if (!res.ok) throw new Error(`Pull failed: ${res.status}`);
|
||||||
const data: SyncPullResponse = await res.json();
|
const data: SyncPullResponse = await res.json();
|
||||||
|
|
||||||
const { contexts, topics, historyEntries, ratings } = data.changes;
|
const { contexts, topics, historyEntries, ratings, imageBlobs } = data.changes;
|
||||||
|
|
||||||
const { imageBlobs } = data.changes;
|
|
||||||
|
|
||||||
await db.transaction('rw', [db.contexts, db.topics, db.historyEntries, db.ratings, db.imageBlobs], async () => {
|
await db.transaction('rw', [db.contexts, db.topics, db.historyEntries, db.ratings, db.imageBlobs], async () => {
|
||||||
for (const serverCtx of contexts) {
|
for (const serverCtx of contexts) {
|
||||||
|
|
@ -73,8 +71,10 @@ async function pullAndMerge(since: Date | null): Promise<string> {
|
||||||
for (const serverBlob of (imageBlobs ?? [])) {
|
for (const serverBlob of (imageBlobs ?? [])) {
|
||||||
const local = await db.imageBlobs.get(serverBlob.id);
|
const local = await db.imageBlobs.get(serverBlob.id);
|
||||||
if (!local || serverBlob.version > local.version) {
|
if (!local || serverBlob.version > local.version) {
|
||||||
// Decode base64 → Blob
|
// Decode base64 → Blob (chunked to avoid stack overflow on large blobs)
|
||||||
const bytes = Uint8Array.from(atob(serverBlob.data), (c) => c.charCodeAt(0));
|
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 });
|
const blobData = new Blob([bytes], { type: serverBlob.mimeType });
|
||||||
await db.imageBlobs.put({
|
await db.imageBlobs.put({
|
||||||
id: serverBlob.id,
|
id: serverBlob.id,
|
||||||
|
|
@ -102,11 +102,17 @@ async function pushAll(): Promise<void> {
|
||||||
db.imageBlobs.toArray(),
|
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(
|
const imageBlobs = await Promise.all(
|
||||||
localBlobs.map(async (b) => {
|
localBlobs.map(async (b) => {
|
||||||
const buf = await b.data.arrayBuffer();
|
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 {
|
return {
|
||||||
id: b.id,
|
id: b.id,
|
||||||
mimeType: b.mimeType,
|
mimeType: b.mimeType,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue