-
Notifications
You must be signed in to change notification settings - Fork 220
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
finalize promise resolved before all files are written to archive #476
Comments
Here is the output for this snippet const someArrayOfItems: string[] = [...];
async function export(req: Request, res: Response, next: NextFunction): Promise<void> {
res.type("application/zip");
res.attachment("export.zip");
const zip = archiver("zip");
zip.pipe(res);
zip.on("drain", () => {
console.log("Drained adding a file to zip");
});
zip.on("warning", (e) => {
console.log(`Warning while adding a file to zip: ${e.message}`);
});
zip.on("finish", () => {
console.log("Finish adding a file to zip");
});
zip.on("close", () => {
console.log("closing zip");
});
zip.on("data", (data) => {
console.log("on data");
});
zip.on("entry", (data) => {
console.log("on entry");
});
let i = 0;
for (const item of someArrayOfItems) {
const buffer = await QRCode.toBuffer(string);
zip.append(buffer, { name: `${i}.png` });
i += 1;
}
console.log("before finalize");
await zip.finalize();
console.log("after finalize");
next();
} Output
It keeps fireing "on data" events even after the |
From the README.md:
From the docs:
Archiver is a streaming interface. Node streams are events-based. I don't know from where you got the idea that |
From the source code and from the TypeScript typings What event represents the end of the archiver queue? As I understand, the "finish" or "close" event should be fired from the archiver when it finishes the |
My question is why the archiver fires the |
Well, now that's a most unfortunate discovery that this was added there 3 years ago and never documented. I would say don't trust this promise because:
Fixing this would be an API-breaking change. I hope this is enough to convince you to just not use it. As I said in a comment on the other issue you commented on, archiver is just a queueing helper on top of zip-stream/tar-stream. I don't even use archiver as I prefer to just do my own queueing and I don't like archiver's API, it's old and has too many problems as you've just found out. EDIT: This event on the consumer stream is what you should probably be listenning to: https://nodejs.org/api/stream.html#stream_event_finish EDIT2: These events are not from archiver, they are from the node streams that you are piping to/from archiver. |
@jntesteves now it makes sense to me. This promise from the |
I'm resolve it.
|
Hey folks, I know this has been closed but: The fact that streaming isn't completed even after calling In my own code I have a const thisArchive = archive;
const streamingCompletedPromise = new Promise<void>((resolve, reject) => {
outputZip.on('close', () => resolve()); // the stream previously defined
thisArchive.on('error', (err: Error) => reject(err));
});
const originalArchiverFinalize = archive.finalize;
archive.finalize = async () => {
await originalArchiverFinalize.call(thisArchive);
await streamingCompletedPromise;
}; Wouldn't it be possible to just update the code so that the normal |
In Express app, when sending a zip archive with big number of files (more than 100 in my case) the archive is opened with error "Unexpected end of data" in 7-zip even though all files are present and successfuly extracted from the archive.
Here is a code snipped that I used:
On small numbers of items the archive is extracted without any errors both with the timeout after
await zip.finalize();
and without it. But on bigger numbers, the archive is correctly extracted only when there is the timeout afterawait zip.finalize();
.It seems like the promise that is returned from the
await zip.finalize();
is resolved before the archive is actually finalizedThe text was updated successfully, but these errors were encountered: