Working with ZIP files in worker scripts

I unfortunately have to fetch a zip file (~50kb) in a worker slightly manipulate the contents and then send the altered zip as the response.

This is far outside my knowledge of javascript and web workers. Could someone post a code sample for me, or is someone open to do some paid consulting on this? We can post the result afterwards here.

I was able to archive this in PHP a while back, but this code has to be ported to JavaScript and instead of using the filesystem it has to happen in the workers memory (I presume).

$zip = new ZipArchive;
$zip->open($path);

for ($index = 0; $index < $zip->numFiles; $index++) {
    $zip->renameIndex($index, str_replace(
        'foo', 'bar', $zip->getNameIndex($index)        
    ));
}

$zip->close();

The best library I can recommend is https://stuk.github.io/jszip/documentation/examples.html since it can work in a browser, thus it’ll likely work in the worker.

I was able to archive this, probably not ideal, but it’s working:

async function modifiedZip(buffer, version) {
  let zip

  const fs = {}
  const modifiedZip = new jszip
  const packagistZip = new jszip

  await packagistZip.loadAsync(buffer)

  packagistZip.sync(() => {
    Object.keys(packagistZip.files).forEach(filename => {
      if (packagistZip.files[filename].dir) {
        return
      }

      packagistZip.files[filename]
        .async('nodebuffer')
        .then(content => fs[filename] = content)
    })
  })

  modifiedZip.sync(() => {
    modifiedZip.folder('my-package-name')

    Object.keys(fs).forEach(filename => {
      modifiedZip.file(
        `my-package-name/${filename}`,
        fs[filename],
        packagistZip.files[filename]
      )
    })

    modifiedZip
      .generateAsync({ type: 'nodebuffer' })
      .then(content => zip = content)
  })

  return zip
}
3 Likes

Thanks for sharing!