user47103
user47103

Reputation: 179

Node.js How to zip an array of images and force browser to download it

as the title says. I have an app that could collect all image urls from an user input url. Now I want to able to zip them and when the user press the download button, it will fires a request contain the array of all the image urls to download.js and let the download.js to process the download.

In addition, I am using express.js and react; the express.js is using port 5000

Someone sent me a working sample code: https://repl.it/@chiKaRau/picture-packer-4-rex-1

However, this code will create its own port 3000

I want to able to process the download on my current port 5000 while express is launch on port 5000

So I changed some code, however, once I pressed the download button, nothing happens (no error and no download)

Would anyone tell me how to solve this? Thank

download.js

        const express = require('express'); 
        let router = express.Router(); 

        const fetch = require('node-fetch') 
        // to get the images const 

        JSZip = require('jszip') 
        // to zip them up 

        const micro = require('micro') 
        // to serve them

        router.post('/download-pics', (req, res) => {    

            const files = [
            {
              url: "https://jeremyliberman.com/static/489f2e7cf7df14bc2c8ac2bc8c76aa59/cb864/avatar.png",
              file: 'avatar.png'
            },
            {
              url: "https://jeremyliberman.com/static/489f2e7cf7df14bc2c8ac2bc8c76aa59/cb864/avatar.png",
              file: 'avatar1.png'
            },
            {
              url: "https://jeremyliberman.com/static/489f2e7cf7df14bc2c8ac2bc8c76aa59/cb864/avatar.png",
              file: 'avatar2.png' }   
            ]

            // Start a simple web service with one route
            // Create an in-memory zip file
            var zip = new JSZip();

            // Fetch each image source
            const request = async () => {
                for (const { file, url } of files) {
                const response = await fetch(url);
                const buffer = await response.buffer();
                zip.file(file, buffer);
              }
            }
            request();

            // Set the name of the zip file in the download
            res.setHeader('Content-Disposition', 'attachment; filename="pictures.zip"')

            // Send the zip file
            zip.generateNodeStream({ type: 'nodebuffer', streamFiles: true })
              .pipe(res).on('finish', function() {
                  console.log("out.zip written.");
              }) })

        //export this router to use in our index.js module.exports = router;

Upvotes: 1

Views: 3167

Answers (1)

bentesha
bentesha

Reputation: 948

Function request returns a promise. You need to wrap the rest of the code after request() in then(() => {})

request()
  .then(() => {
    // Set the name of the zip file in the download
    res.setHeader('Content-Disposition', 'attachment; filename="pictures.zip"')

    // Send the zip file
    zip.generateNodeStream({ type: 'nodebuffer', streamFiles: true })
      .pipe(res).on('finish', function() {
          console.log("out.zip written.");
      })
  })

Upvotes: 1

Related Questions