2

I tried to the following function but it only allows me download 1 photo,
so I am finding a method to zip the images and download it.

But I have searched lots of post in stackoverflow and cannot find a correct way to do it.

function downloadPhotos() {
  let files = [{
    image: "abc.com/image/01"
  }, {
    image: "abc.com/image/02"
  }]
  files.map(file => {
    const link = document.createElement('a');
    link.href = file.image;
    link.setAttribute('download', `sample`)
    document.body.appendChild(link);
    link.click();
    link.parentNode.removeChild(link);
  })
}
Mosh Feu
  • 28,354
  • 16
  • 88
  • 135
CCCC
  • 5,665
  • 4
  • 41
  • 88
  • 1
    Try https://www.npmjs.com/package/jszip – Dilshan Feb 28 '21 at 09:01
  • Not exactly your case, but you can start from here https://stackoverflow.com/a/61177270/12610347 basically the only difference is that you get your images from normal links, not from `base64` – x00 Feb 28 '21 at 09:13
  • Does [this](https://stackoverflow.com/q/27746982/863110) help? – Mosh Feu Feb 28 '21 at 12:46

1 Answers1

3

You'll need a ZIP archive generation library. You can use fflate to do this quickly and in a streaming fashion to save memory.

import { Zip, ZipPassThrough } from 'fflate';
import streamSaver from 'streamsaver';

function downloadPhotos() {
  let files = [{
    image: "https://example.com/image1"
  }, {
    image: "https://example.com/image2"
  }];
  const zip = new Zip();
  const rs = new ReadableStream({
    start(controller) {
      zip.ondata = (err, dat, final) => {
        if (err) {
          controller.error(err);
        } else {
          controller.enqueue(dat);
          if (final) controller.close();
        }
      }
    }
  });
  rs.pipeTo(streamSaver.createWriteStream('example.zip'));
  return Promise.all(files.map(async meta => {
    const stream = (await fetch(meta.image)).body;
    const file = new ZipPassThrough(meta.image);
    zip.add(file);
    const reader = stream.getReader();
    while (true) {
      const { value, done } = await reader.read();
      if (done) {
        file.push(new Uint8Array(0), true);
        return;
      };
      file.push(value);
    }
  })).then(() => zip.end());
}

This will stream the download and thereby maximize performance.

101arrowz
  • 1,825
  • 7
  • 15