daraosn / node-zip

217 stars 38 forks source link

Is it possible to create a zip from an existing file/folder structure? #18

Open thinkloop opened 7 years ago

thinkloop commented 7 years ago

Hello, thanks a lot for the lib.

Is it possible to create a zip from existing file/folder structures?

I would like to do something like:

const fs = require("fs");
const Zip = require('node-zip');
const zip = new Zip();

zip.folder('./src/existing-folder-with-files-and-subfolders');
var data = zip.generate({base64: false, compression: 'DEFLATE'});
fs.writeFileSync('./output/zipped-files-exactly-as-they-appear-in-filesystem.zip', data, 'binary');

Instead of creating new files and folders from within the zip utility. Is this possible?

adelriosantiago commented 7 years ago

Someone has a workaround for this? I also need to compress a folder.

thinkloop commented 7 years ago

I used zip-folder.

kkuatov commented 7 years ago

I also needed such a functionality, but seems like there is no way to do it simply. So I did all folder creation and adding files to zip file using methods from JSZip library on which this library is based.

ecmadao commented 7 years ago

@thinkloop @adelriosantiago @kkuatov

If your folder structure is not soooo deep, it's easy to walk the folder and add each file to zip. For example:

const fs = require('fs');
const path = require('path');
const NodeZip = require('node-zip');

const zip = new NodeZip();
const BUILD_PATH = './build';
const OUTPUT_PATH = path.join(__dirname, `${BUILD_PATH}.zip`);
const ALL_FILES = {};

const isFolder = folderPath => fs.statSync(folderPath).isDirectory();

const folderWalker = (folder = './', lastFolder = './') => {
  const folderPath = path.join(__dirname, BUILD_PATH, lastFolder, folder);
  fs.readdirSync(folderPath)
    .filter(filename => filename[0] !== '.')
    .forEach((file) => {
      const fullpath = path.resolve(__dirname, BUILD_PATH, lastFolder, folder, file);
      if (isFolder(fullpath)) {
        const fatherFolder = path.join(lastFolder, folder);
        folderWalker(file, fatherFolder);
      } else {
        const relativePath = path.join(lastFolder, folder, file);
        ALL_FILES[fullpath] = relativePath;
      }
    });
};

const zipFolder = (folder) => {
  folderWalker(folder);
  Object.keys(ALL_FILES).forEach((fullpath) => {
    const relativePath = ALL_FILES[fullpath];
    zip.file(relativePath, fs.readFileSync(fullpath));
  });
  const data = zip.generate({ base64: false, compression: 'DEFLATE' });
  fs.writeFileSync(OUTPUT_PATH, data, 'binary');
};

zipFolder();

Check Gist here to see full code.