Should i call "zip.end()" with ondata finish === true? #65
Answered
by
101arrowz
crapthings
asked this question in
Q&A
-
export function downloadAsZip (filename, downloads) {
const fileStream = streamSaver.createWriteStream(`${filename}.zip`);
const writer = fileStream.getWriter();
const zip = new fflate.Zip();
zip.ondata = writeStreamForDownload;
downloads?.forEach(({ filename, downloadUrl }) => fetch(downloadUrl).then(pipeZipfile(filename)));
function writeStreamForDownload (err, chunk, finish) {
writer.write(chunk);
if (err || finish) {
return writer.close();
}
};
function pipeZipfile (filename) {
return async function (response) {
const file = new fflate.ZipPassThrough(filename);
zip.add(file);
const reader = response.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) {
file.push(new Uint8Array(0), true);
break;
}
file.push(value);
};
zip.end();
};
};
}; i can get proper zip file by these code, but i don't know why i put zip.end into a forEach loop it still works |
Beta Was this translation helpful? Give feedback.
Answered by
101arrowz
Jun 2, 2021
Replies: 1 comment 1 reply
-
This only works because of the delay in the data arrival; you shouldn't use this solution. Instead, call export function downloadAsZip (filename, downloads) {
const fileStream = streamSaver.createWriteStream(`${filename}.zip`);
const writer = fileStream.getWriter();
const zip = new fflate.Zip();
zip.ondata = writeStreamForDownload;
downloads?.forEach(({ filename, downloadUrl }) => fetch(downloadUrl).then(pipeZipfile(filename)));
// Now all the zip.add() calls executed synchronously, so this is safe to call
zip.end();
function writeStreamForDownload (err, chunk, finish) {
writer.write(chunk);
if (err || finish) {
return writer.close();
}
};
function pipeZipfile (filename) {
// I moved this out of the async function so it executes synchronously
const file = new fflate.ZipPassThrough(filename);
zip.add(file);
return async function (response) {
const reader = response.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) {
file.push(new Uint8Array(0), true);
break;
}
file.push(value);
};
};
};
}; |
Beta Was this translation helpful? Give feedback.
1 reply
Answer selected by
101arrowz
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This only works because of the delay in the data arrival; you shouldn't use this solution. Instead, call
zip.end()
one time after you have calledzip.add()
with every file you need. You also have to make sure you don't call accidentally callzip.add()
afterzip.end()
, e.g. if you put theadd()
calls into the event loop withasync/await
. Try this: