fix: double closed zip

This commit is contained in:
monoid 2025-10-27 02:13:12 +09:00
parent fe5ed4c4aa
commit a319dc3337
2 changed files with 13 additions and 7 deletions

View file

@ -81,9 +81,9 @@ export async function renderComicPage({ path, page, reqHeaders, set }: RenderOpt
if (await setHeadersForEntry(entry, reqHeaders, set)) { if (await setHeadersForEntry(entry, reqHeaders, set)) {
return null; return null;
} }
const readStream = await createReadableStreamFromZip(zip.reader, entry); const abort = new AbortController();
const readStream = await createReadableStreamFromZip(zip.reader, entry, { signal: abort.signal });
// Ensure zip file is closed after stream ends // Ensure zip file is closed after stream ends
const streamWithCleanup = new ReadableStream({ const streamWithCleanup = new ReadableStream({
async start(controller) { async start(controller) {
@ -94,6 +94,7 @@ export async function renderComicPage({ path, page, reqHeaders, set }: RenderOpt
if (done) break; if (done) break;
controller.enqueue(value); controller.enqueue(value);
} }
abort.signal.throwIfAborted()
controller.close(); controller.close();
} catch (error) { } catch (error) {
controller.error(error); controller.error(error);
@ -102,8 +103,8 @@ export async function renderComicPage({ path, page, reqHeaders, set }: RenderOpt
await zip.reader.close(); await zip.reader.close();
} }
}, },
cancel: async () => { cancel: (reason) => {
await zip.reader.close(); abort.abort();
} }
}); });

View file

@ -98,11 +98,16 @@ export async function entriesByNaturalOrder(zip: ZipReader<FileHandle>) {
return ret; return ret;
} }
export async function createReadableStreamFromZip(_zip: ZipReader<FileHandle>, entry: Entry): Promise<ReadableStream> { export async function createReadableStreamFromZip(_zip: ZipReader<FileHandle>, entry: Entry, option?: { signal?: AbortSignal }): Promise<ReadableStream> {
if (entry.getData === undefined) { if (entry.getData === undefined) {
throw new Error("entry.getData is undefined"); throw new Error("entry.getData is undefined");
} }
const stream = new TransformStream<Uint8Array, Uint8Array>(); const stream = new TransformStream<Uint8Array, Uint8Array>();
entry.getData(stream.writable); entry.getData(stream.writable, {
signal: option?.signal,
}).catch(e => {
// ignore error.
// error is handled by stream.readable
});
return stream.readable; return stream.readable;
} }