Stuk / jszip

Create, read and edit .zip files with Javascript
https://stuk.github.io/jszip/
Other
9.77k stars 1.3k forks source link

How to cancel / abort archive creation #594

Open pippo111 opened 5 years ago

pippo111 commented 5 years ago

When using generateAsync you cannot cancel its running.

When using StreamHelper you can pause its running, but there is no way to just abort accumulation function.

Is there a way to abort accumulate or generateAsync function and free memory and cpu resources ? It is crucial for example to implement "cancel" functionality to the user.

jimmywarting commented 5 years ago

I rolled my own < 200 line archiver based on whatwg-Streams. It doesn't hold anything in memory to try and create a blob or anything.

https://github.com/jimmywarting/StreamSaver.js/blob/ee450e2054c3358c356f98bb7eab2fc23f94e0cb/examples/zip-stream.js

It has support for abort, more importantly it don't generate any archive unless you have a consumer that reads from the readableStream. (no read == no creation) Also if any of the streams that it's piped to get's aborted/canceld the archive creation will stop too.

I have made an example how to generate a zip using streamSaver that pipes the zip archive directly to the disc https://jimmywarting.github.io/StreamSaver.js/examples/saving-multiple-files.html

Note that it don't support any compression, zip reading or zip64, so the maxium size is 4gb

101arrowz commented 3 years ago

This is a bit late, but you may consider using fflate for higher performance, parallelization, smaller bundle, and cancellation support.

pippo111 commented 3 years ago

@101arrowz Thanks, actually I will try it with my new upcoming project, so perfect timing!

huzunjie commented 1 year ago

I am trying to solve the "abort" problem with the following solution, and it seems feasible?

  let dirName = 'xxx';

  const zip = new JSZip();

  const zipHelper = zip.generateInternalStream({
    type: 'blob',
    compression: 'DEFLATE',
    compressionOptions: {
      level: 6,
    },
  });

  let isStop = false;
  const stop = () => {
    zipHelper.pause();
    zip.remove(dirName);
    zipHelper._worker.end();
    isStop = true;
  };

  zipHelper
      .accumulate((metadata) => {
        if (isStop) return;
        // ...metadata.percent...
      })
      .then(
        (blob) => {
          if (isStop) return;
          //....
        },
        (zipErr) => {
          if (isDone) return;
          //....
        }
      );