Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to merge and unzip (.zip, .z01, .z02) in javascript (client side only)?

I am trying to download the splitted zip file coming from api call in parts (.zip, .z01, .z02) etc. In Javascript I want to download these files on the fly and create a combined .zip file and then save the unzipped file. (i don't need to create a combined zip) I simply need test.pdf file which which has been splitted to multiple zip. I want to download that pdf file.

e.g. test.pdf (18 mb) is splitted into two zip files of (.zip 10mb) and (.z01 8mb). currently I am downloading them as blob and then merging them. the resulting zip is currupted. below is the code I tried.

Promise.all([
  axios.get(`https://testapi.com/folder/file.zip`, {
    responseType: "blob",
    headers: {
      Accept: "application/json",
    },
  }),
  axios.get(`https://testapi.com/folder/file.z01`, {
    responseType: "blob",
    headers: {
      Accept: "application/json",
    },
  }),
]).then((obj) => {
  let blob: any = [];
  obj.forEach((e: any) => {
    blob.push(e.data);
  });
  const newBlob = new Blob(blob, { type: "octet/stream" });
  saveAs(newBlob, "zip.zip"); // but it's currupted
});
like image 460
Taj Khan Avatar asked Jun 05 '21 05:06

Taj Khan


People also ask

How do I unzip a zip 001 file in Linux?

To unzip the example above, you can right-click on the MyImageData. zip. 001 file (after you've installed 7-Zip), select the 7-Zip menu, and then choose one of the "extract" options.

How do you zip a javascript file?

Start by grabbing the JSZip library , which happens to work in all major browsers. Once the library is available within the page, generating a Zip file is really just a few lines of code: var zip = new JSZip(); // Add an top-level, arbitrary text file with contents zip.

How do I unzip a node js file?

You can simply extract the existing zip files also by using "unzip". It will work for any size files and you need to add it as a dependency from npm. Please explain what unzip is and if it's a built in package or requires you to npm install it.

How to unzip multiple ZIP files into one zip file?

Put all your zip files in the same directory: zip_file.z01, zip_file.z02, zip_file.z03, ..., zip_file.zip As noted in the comments, using a - sign after the command line option -s joins all the zip files together and writes it as a single zip file which you can then extract using the unzip command. Show activity on this post.

How do I merge split files with ZIP?

Click the Merger button on the right-hand page of a ZIP free application. Alternatively, drag and drop a ZIP file can be done inside the file drop area. Files can be merged with a click on ‘MERGE’. When merged files are shown as an email, we instantly download and view them. How Do I Merge Split Files With 7-Zip?

What do I do with the Z01 and Z02 files?

For example, if your download contains three parts, your folder should contain one .zip file, a .z01 file, and a .z02 file. What do I do with the .z01 and .z02 files? You do not need to do anything with the .z01 and .z02 files. WinZip and WinRAR will extract the contents of the files for you.

How to merge two or more JavaScript objects?

Summary: in this tutorial, you will learn how to merge two or more JavaScript objects and create a new object that combines the properties of all the objects. To merge objects into a new one that has all properties of the merged objects, you have two options: Use a spread operator ( ...) Merge objects using the spread operator ( ...)


1 Answers

You could use JSZip and FileSaver in order to achieve this. Note that the files are ordered alphabetically in the input so this snippet requires your files to be named accordingly. I have used an input in order to make testing easier, you could easily adapt it to axios requests for each file.

The snippet actually doesn't work on this web page because the downloads are disallowed by the snippet iframe's policy so you have to try it by other means.

const objectWithoutProperties = (obj, keys) => {
  const target = {};
  for (let i in obj) {
    if (keys.indexOf(i) >= 0) continue;
    if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
    target[i] = obj[i];
  }
  return target;
}

const mergeFiles = (a, b) => {
  if (!a) return b;
  const intersect = Object.keys(a.files).filter((x) =>
    Object.keys(b.files).includes(x)
  );

  a.files = { ...a.files, ...objectWithoutProperties(b.files, intersect) };

  return Promise.all(
    intersect.map((file) =>
      Promise.all([
        a.file(file).async("arraybuffer"),
        b.file(file).async("arraybuffer"),
      ])
        .then((x) => new Blob(x))
        .then((x) => a.file(file, x))
    )
  ).then(() => a);
};

const MultipleZipMerger = () => {
  function change(e) {
    Promise.all([...e.target.files].map(JSZip.loadAsync))
      .then((x) =>
        x.reduce(
          (acc, cur) => acc.then((x) => mergeFiles(x, cur)),
          Promise.resolve()
        )
      )
      .then((x) => x.generateAsync({ type: "blob" }))
      .then((x) => saveAs(x, "hello.zip"));
  }
  
  return <input onChange={change} type="file" multiple />;
};

ReactDOM.render(<MultipleZipMerger />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.6.0/jszip.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip-utils/0.1.0/jszip-utils.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.0/FileSaver.min.js"></script>

<div id="root"></div>

This is a standalone version of this code which you can test as a local file:

<!doctype html>

<html>
</head>

<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.6.0/jszip.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip-utils/0.1.0/jszip-utils.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.0/FileSaver.min.js"></script>

<div id="root"></div>
<script>
  
const objectWithoutProperties = (obj, keys) => {
  const target = {};
  for (let i in obj) {
    if (keys.indexOf(i) >= 0) continue;
    if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
    target[i] = obj[i];
  }
  return target;
}

const mergeFiles = (a, b) => {
  if (!a) return b;
  const intersect = Object.keys(a.files).filter((x) =>
    Object.keys(b.files).includes(x)
  );

  a.files = { ...a.files, ...objectWithoutProperties(b.files, intersect) };

  return Promise.all(
    intersect.map((file) =>
      Promise.all([
        a.file(file).async("arraybuffer"),
        b.file(file).async("arraybuffer"),
      ])
        .then((x) => new Blob(x))
        .then((x) => a.file(file, x))
    )
  ).then(() => a);
};

const MultipleZipMerger = () => {
  function change(e) {
    Promise.all([...e.target.files].map(JSZip.loadAsync))
      .then((x) =>
        x.reduce(
          (acc, cur) => acc.then((x) => mergeFiles(x, cur)),
          Promise.resolve()
        )
      )
      .then((x) => x.generateAsync({ type: "blob" }))
      .then((x) => saveAs(x, "hello.zip"));
  }

  return React.createElement("input", {
    onChange: change,
    type: "file",
    multiple: true,
  });
};

ReactDOM.render(
  React.createElement(MultipleZipMerger, null),
  document.getElementById("root")
);

  
</script>
</body>
</html>
like image 85
Guerric P Avatar answered Oct 17 '22 03:10

Guerric P