archiverjs / node-archiver

a streaming interface for archive generation
https://www.archiverjs.com
MIT License
2.8k stars 220 forks source link

Archive without root folder in .zip #374

Open gemmi-arts opened 5 years ago

gemmi-arts commented 5 years ago

Hello,

I'm using node-archiver to archive folder "export" with photos inside.

Everything works ok but inside archive I got folder 'offers' and photos are in this folder.

I would like to have like a "flat" .zip, so when I'll unpack my .zip it unpack photos without that 'offers' folder.

My code:

  const folderPath = '/export/.';
  const output = fs.createWriteStream('test/offers.zip');
  const archive = archiver('zip');
  archive.pipe(output);
  archive.directory(folderPath, false);
  archive.finalize();

What I'm getting after unpacking: 1

What I would like to get: 2

How can I achieve this?

binggg commented 5 years ago

@gemmi-arts Can you try to use terminal to unzip the offers.zip.

Just like

unzip offers.zip

Becasue the unzip software sometimes use the filename as the unzip directory.

cksachdev commented 3 years ago

@gemmi-arts I have a similar issue, have you figured out a solution to this?

gemmi-arts commented 3 years ago

@gemmi-arts I have a similar issue, have you figured out a solution to this?

@cksachdev Unfortunately not :/

cksachdev commented 3 years ago

@gemmi-arts I have figured out, although I had to downgrade to v4.0.2. I looked into the code base and test cases to figure out a solution. I had to use archive.glob method. Below is a sample code:

const _ = require('lodash');
const fs = require('fs');
const archiver = require('archiver');
const path = require('path');
const jsonfile = require('jsonfile');

let courseFile = './template/src/course/en/course.json';
let courseObject = jsonfile.readFileSync(courseFile);

const config = {
    newCourseArchive: `${__dirname}/zips/${courseObject.title}.zip`,
};

writeArchive();
function writeArchive() {
    const output = fs.createWriteStream(config.newCourseArchive);
    const archive = archiver('zip', {
        zlib: {
            level: 9,
        }, // Sets the compression level.
    });
    output.on('close', function () {
        console.log(archive.pointer() + ' total bytes');
        console.log('archiver has been finalized and the output file descriptor has closed.');

        console.log(`${config.newCourseArchive} is ready!`);
    });

    output.on('end', function () {
        console.log('Data has been drained');
    });

    archive.on('warning', function (err) {
        if (err.code === 'ENOENT') {
            // log warning
        } else {
            // throw error
            throw err;
        }
    });
    archive.on('error', function (err) {
        throw err;
    });

    archive.pipe(output);
    console.log(__dirname);
    archive.glob(
        `**/*`,
        {
            cwd: path.join('template/'),
            ignore: [
                'build/**/*',
                'node_modules/**/*',
                'zips/**/*',
                'src/theme copy/**',
                'srr/**/*',
                '*.zip',
                'build',
                'node_modules',
                'zips',
                'srr',
            ],
        },
        {
            prefix: '',
        },
    );
    archive.finalize();
}

Here, first parameter is the glob pattern. I need to select everything. second parameter is an object. cwd: Specify in which directory you want to apply the glob pattern, i.e. select everything. Here select everything in template directory. ignore: Array of patterns which should be excluded from zipping. third parameter is an object. prefix: this if its set to blank, it will not create a folder This addresses your problem

Below is a link to test case: https://github.com/archiverjs/node-archiver/blob/f646f86e166c7609f1321ad2d3cbd34ed24201fb/test/archiver.js#L47

Hope it helps.

phiberber commented 3 years ago

Facing the same problem, where when using an absolute path, it creates a zip with the whole path as folders, that's; the zip comes with a "Users" folder, that has a folder with my Windows username inside, etc...