Cara Membuat File Zip Dari URL Menggunakan Nodejs - CRUDPRO

Cara Membuat File Zip Dari URL Menggunakan Nodejs

Cara Membuat File Zip Dari URL Menggunakan Nodejs

Jadi belakangan ini saya sedang mengerjakan pembuatan file zip dari beberapa url. Agak menantang tapi saya menemukan cara untuk melakukannya. Masalahnya, package yang saya gunakan, tidak mendukung async menunggu langsung dari bat. Jadi saya harus mencari tahu sendiri.

Archiver adalah package yang sangat populer dengan estimasi 6 juta unduhan setiap minggunya. Sangat mudah membuat file zip dari lokal atau url. Masalahnya, menjadi rumit ketika lebih dari satu file.

Pertama, Anda perlu express-async-handler agar aplikasi ekspres Anda dapat menangani kondisi async menunggu.

const asyncHandler = require("express-async-handler");

Anda juga memerlukan beberapa hal lain untuk menangani path dimana file akan disimpan sementara sebelum diberikan ke sisi client.

const express = require("express");
const app = express();
const path = require("path");

const fs = require("fs");
const archiver = require("archiver");

const axios = require("axios");

const asyncHandler = require("express-async-handler");

const moment = require("moment");

Kode lengkap tersedia di repositori github saya.

Pada url utama, saya menyediakan file html dasar dengan tombol unduh di dalamnya. Tombol unduh akan mengunduh file zip yang ada di /download url.

app.get("/", (req, res) => {
  res.sendFile(path.join(__dirname, "index.html"));
});

Pertama, Anda perlu menginisialisasi pengarsipan menggunakan kode ini

const archive = archiver("zip", {
  zlib: { level: 9 }, // Sets the compression level.
});

// pipe archive data to the file
archive.pipe(output);

Kemudian Anda perlu membuat daftar url file yang ingin Anda masukkan ke dalam zip. Dalam hal ini, saya menggunakan gambar fruit secara acak dari google.

const url = [
  "https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/assortment-of-colorful-ripe-tropical-fruits-top-royalty-free-image-995518546-1564092355.jpg",
  "https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/assortment-of-colorful-ripe-tropical-fruits-top-royalty-free-image-995518546-1564092355.jpg",
  "https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/assortment-of-colorful-ripe-tropical-fruits-top-royalty-free-image-995518546-1564092355.jpg",
  "https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/assortment-of-colorful-ripe-tropical-fruits-top-royalty-free-image-995518546-1564092355.jpg",
  "https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/assortment-of-colorful-ripe-tropical-fruits-top-royalty-free-image-995518546-1564092355.jpg",
];

Kami akan menggunakan fungsi Promise.all() untuk menunggu sampai setiap url telah ditambahkan ke dalam file zip. Setelah itu, kami memanggil fungsi finalisasi. Langkah ini sangat penting karena bagaimanapun juga, file zip akan rusak.

url.forEach((u, i) => {
  promiseArray.push(
    new Promise(async (resolve, reject) => {
      const response = await axios.get(u, { responseType: "arraybuffer" });

      const buffer = Buffer.from(response.data, "binary");

      const fileName = u.split("/").pop();

      if (i < 2) {
        archive.append(buffer, {
          name: moment().valueOf() + fileName,
         });
      } else {
        archive.append(buffer, { name: moment().valueOf() + fileName });
      }

      resolve();
    })
  );
});

Promise.all(promiseArray).then(async (values) => {
  await archive.finalize();
});

Saya menggunakan package moment() untuk menghasilkan nomor acak untuk memberi nama file. Kami menambahkan setiap file ke objek arsip.

output.on("close", function () {
  console.log(archive.pointer() + " total bytes");
  console.log(
    "archiver has been finalized and the output file descriptor has closed."
  );

  res.download(`./${name}.zip`, `${name}.zip`);

  setTimeout(() => {
    fs.rmSync(`./${name}.zip`, {
      force: true,
    });
  }, 10000);
});

// This event is fired when the data source is drained no matter what was the data source.
// It is not part of this library but rather from the NodeJS Stream API.
// @see: https://nodejs.org/api/stream.html#stream_event_end
output.on("end", function () {
  console.log("Data has been drained");
});

// good practice to catch warnings (ie stat failures and other non-blocking errors)
archive.on("warning", function (err) {
  if (err.code === "ENOENT") {
    // log warning
  } else {
    // throw error
    throw err;
  }
});

archive.on("error", function (err) {
  throw err;
});

Selain itu, kita bisa menggunakan fungsi callback saat file selesai. Dalam hal ini, saya ingin menghapus file yang di-zip setelah dikirim ke klien. Saya menggunakan baris berikut ini untuk melakukan pekerjaan

setTimeout(() => {
  fs.rmSync(`./${name}.zip`, {
    force: true,
  });
}, 10000);