Node.js를 사용하여 전체 디렉토리를 압축해야합니다.


107

Node.js를 사용하여 전체 디렉토리를 압축해야합니다. 현재 node-zip을 사용하고 있으며 프로세스가 실행될 때마다 잘못된 ZIP 파일이 생성됩니다 ( 이 Github 문제 에서 볼 수 있듯이 ).

디렉토리를 압축 할 수있는 또 다른 더 나은 Node.js 옵션이 있습니까?

편집 : 아카이버 를 사용하여 끝났습니다.

writeZip = function(dir,name) {
var zip = new JSZip(),
    code = zip.folder(dir),
    output = zip.generate(),
    filename = ['jsd-',name,'.zip'].join('');

fs.writeFileSync(baseDir + filename, output);
console.log('creating ' + filename);
};

매개 변수의 샘플 값 :

dir = /tmp/jsd-<randomstring>/
name = <randomstring>

업데이트 : 내가 사용한 구현에 대해 묻는 사람들 을 위해 내 다운로더에 대한 링크가 있습니다 .


3
Twitter의 누군가가 child_process API를 제안하고 시스템 ZIP을 호출하기 만하면됩니다. nodejs.org/api/child_process.html
commadelimited

1
나는 child_process 접근 방식을 시도했습니다. 두 가지주의 사항이 있습니다. 1) unix zip명령은 압축 파일에 현재 작업 디렉토리의 모든 상위 폴더 계층을 포함합니다. 이것은 당신에게 괜찮을지도 모르지만 그것은 나를위한 것이 아닙니다. 또한 child_process의 현재 작업 디렉토리를 변경해도 결과에 영향을 미치지 않습니다. 2) 이 문제를 극복하려면을 사용 pushd하여 zip 및을 폴더로 이동해야 zip -r하지만 pushd / bin / sh가 아닌 bash에 내장되어 있으므로 / bin / bash도 사용해야합니다. 내 특정한 경우에는 이것이 불가능했습니다. 그냥주의하세요.
johnozbay

2
@johnozbay 노드의 child_process.execAPI를 사용하면 명령을 실행할 cwd를 지정할 수 있습니다. CWD를 변경하면 상위 폴더 계층 문제가 해결됩니다. 또한 필요하지 않은 문제도 해결합니다 pushd. 나는 child_process를 완전히 추천합니다.
Govind Rai

1
stackoverflow.com/a/49970368/2757916 child_process api를 사용하는 네이티브 nodejs 솔루션. 2 줄의 코드. 타사 라이브러리가 없습니다.
Govind Rai

@GovindRai 많은 감사합니다!
johnozbay

답변:


124

결국 아카이버 lib 를 사용하게되었습니다 . 잘 작동합니다.

var file_system = require('fs');
var archiver = require('archiver');

var output = file_system.createWriteStream('target.zip');
var archive = archiver('zip');

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

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

archive.pipe(output);

// append files from a sub-directory and naming it `new-subdir` within the archive (see docs for more options):
archive.directory(source_dir, false);
archive.finalize();

1
이 작업을 수행하는 방법에 대한 예가없는 것 같습니다. 수행 한 작업을 공유해 주시겠습니까?
Sinetheta

1
불행히도 아카이버는 현재 파일 이름에서 유니 코드 문자를 지원하지 않습니다. 에보고 github.com/ctalkington/node-archiver/issues/90 .
아이

2
모든 파일과 디렉토리를 재귀 적으로 포함하는 방법 (숨겨진 파일 / 디렉토리도 포함)?
Ionică Bizău

12
Archiver는 이제 이것을 더욱 간단하게 만듭니다. 오히려 대량 () 메소드를 사용하는 것보다, 당신은 지금 디렉토리 ()를 사용할 수 있습니다 npmjs.com/package/archiver#directory-dirpath-destpath-data
조쉬 펠드만

14
.bulk사용되지 않는 것입니다
chovy은

46

나는 새로운 것을 보여주는 척하지 않고 (나와 같은) 코드에서 Promise 함수를 사용하는 것을 좋아하는 사람들을 위해 위의 솔루션을 요약하고 싶습니다.

const archiver = require('archiver');

/**
 * @param {String} source
 * @param {String} out
 * @returns {Promise}
 */
function zipDirectory(source, out) {
  const archive = archiver('zip', { zlib: { level: 9 }});
  const stream = fs.createWriteStream(out);

  return new Promise((resolve, reject) => {
    archive
      .directory(source, false)
      .on('error', err => reject(err))
      .pipe(stream)
    ;

    stream.on('close', () => resolve());
    archive.finalize();
  });
}

누군가를 도울 수 있기를 바랍니다.)


여기서 "아웃"이란 정확히 무엇입니까? 나는 소스 디렉토리의 경로입니다 가정

/User/mypc/mydir/test.zip : 같은 @Tarun 전체 우편의 경로
D.Dimitrioglo

zip 파일의 압축을 풀 수 없습니다. 조작은 허용되지 않습니다
제이크

@ ekaj_03 사용자가 지정한 디렉토리에 충분한 권한이 있는지 확인하십시오
D.Dimitrioglo

1
@D. Dimitrioglo 모두 좋습니다. 소스 디렉토리 문제였습니다. 감사합니다 :)
Jake

17

child_process이를 위해 Node의 네이티브 API를 사용하세요.

타사 라이브러리가 필요하지 않습니다. 두 줄의 코드.

const child_process = require("child_process");
child_process.execSync(`zip -r DESIRED_NAME_OF_ZIP_FILE_HERE *`, {
  cwd: PATH_TO_FOLDER_YOU_WANT_ZIPPED_HERE
});

동기식 API를 사용하고 있습니다. child_process.exec(path, options, callback)비동기가 필요한 경우 사용할 수 있습니다 . 요청을 더 세부적으로 조정하기 위해 CWD를 지정하는 것보다 훨씬 더 많은 옵션이 있습니다. exec / execSync 문서를 참조하십시오 .


참고 : 이 예제는 시스템에 zip 유틸리티가 설치되어 있다고 가정합니다 (적어도 OSX와 함께 제공됨). 일부 운영 체제에는 유틸리티가 설치되어 있지 않을 수 있습니다 (예 : AWS Lambda 런타임에는 설치되지 않음). 이 경우 여기 에서 쉽게 zip 유틸리티 바이너리를 가져 와서 애플리케이션 소스 코드와 함께 패키징하거나 (AWS Lambda의 경우 Lambda 계층에서도 패키징 할 수 있음) 타사 모듈을 사용해야합니다. (그 중 NPM에 많은 것이 있습니다). ZIP 유틸리티는 수십 년 동안 시도되고 테스트 되었기 때문에 이전 접근 방식을 선호합니다.


9
불행히도 zip.
janpio 2019

3
내 프로젝트에서 수십 개의 외부 라이브러리를 피하기 위해이 솔루션을 사용했습니다
EAzevedo

말이되지만 내가 틀리지 않다면 이것은 Windows 사용자를 다시 망친다. Windows 사용자를 생각하십시오!
Mathijs Segers

트윗 담아 가기 그래서 Windows 사용자도 얻을 수 있도록 바이너리에 대한 링크를 포함 시켰습니다! :)
Govind Rai

컴퓨터 디렉토리가 아닌 프로젝트 내의 디렉토리에서 작동하도록하는 방법이 있습니까?
Matt Croak

13

Archive.bulk이제 더 이상 사용되지 않으며이를 위해 사용할 새 메서드는 glob입니다 .

var fileName =   'zipOutput.zip'
var fileOutput = fs.createWriteStream(fileName);

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

archive.pipe(fileOutput);
archive.glob("../dist/**/*"); //some glob pattern here
archive.glob("../dist/.htaccess"); //another glob pattern
// add as many as you like
archive.on('error', function(err){
    throw err;
});
archive.finalize();

2
이것에 대해 궁금해서, 그들은 대량이 더 이상 사용되지 않는다고 말했지만 대신 사용할 기능을 제안하지 않았습니다.
jarodsmk

1
"소스"디렉토리를 어떻게 지정합니까?
Dreams

접근 아래에 한 번보십시오 : jsonworld.wordpress.com/2019/09/07/...
SONI 쿠마리에게

2020 : archive.directory ()가 훨씬 더 간단합니다!
OhadR


9

이것은 폴더를 한 줄로 압축 하는 또 다른 라이브러리입니다. zip-local

var zipper = require('zip-local');

zipper.sync.zip("./hello/world/").compress().save("pack.zip");

4
나를 위해 인터넷에서 사용할 수있는 다른 사람의 다스와는 달리, 마법처럼 일했다거나하는 항상 '0 바이트'파일 생성, 위에서 언급 한
세르게이 Pleshakov

4

결과를 응답 개체로 파이프하려면 (로컬에 저장하지 않고 zip을 다운로드해야하는 시나리오)

 archive.pipe(res);

디렉토리의 내용에 액세스하기위한 Sam의 힌트가 저에게 효과적이었습니다.

src: ["**/*"]

3

Adm-zip에는 기존 아카이브 https://github.com/cthackers/adm-zip/issues/64 를 압축하는 데 문제가 있을뿐만 아니라 바이너리 파일 압축으로 인한 손상이 있습니다.

또한 node-zip https://github.com/daraosn/node-zip/issues/4에서 압축 손상 문제가 발생했습니다.

node-archiver는 압축에 잘 작동하는 유일한 것으로 보이지만 압축 해제 기능이 없습니다.


1
어떤 노드 아카이브에 대해 이야기하고 있습니까? : github.com/archiverjs/node-archiver; github.com/richardbolt/node-archiver
biphobe

@firian 그는 Archiver라고 말하지 않았고 Adm-zip이라고 말했습니다.
Francis Pelland

5
@FrancisPelland Umm, 마지막 문장에서 그는 " 노드 아카이브가 작동하는 것처럼 보이는 유일한 사람입니다 "라고 썼습니다 . 그게 제가 말하는 것입니다.
biphobe

나는 그가 고기 npmjs.com/package/archiver
OhadR


1

이후 archiver오랫동안 웹팩의 새 버전과 호환되지 않습니다, 내가 사용하는 것이 좋습니다 지퍼 lib 디렉토리 .

var zl = require("zip-lib");

zl.archiveFolder("path/to/folder", "path/to/target.zip").then(function () {
    console.log("done");
}, function (err) {
    console.log(err);
});

0

간단한 방법으로 시도 할 수 있습니다.

설치 zip-dir:

npm install zip-dir

그리고 그것을 사용하십시오

var zipdir = require('zip-dir');

let foldername =  src_path.split('/').pop() 
    zipdir(<<src_path>>, { saveTo: 'demo.zip' }, function (err, buffer) {

    });

zip 폴더를 만들기 위해 매개 변수를 추가 할 수 있습니까? 압축 수준 및 크기와 같은 경우 어떻게해야합니까?
Trang D

0

내 프로젝트를 통해 리팩토링하는 데 너무 많은 노력이 필요하기 때문에 JSZip을 에뮬레이트하기 위해 아카이버를 래핑했습니다. 나는 Archiver가 최선의 선택이 아닐 수도 있다는 것을 이해하지만 여기 있습니다.

// USAGE:
const zip=JSZipStream.to(myFileLocation)
    .onDone(()=>{})
    .onError(()=>{});

zip.file('something.txt','My content');
zip.folder('myfolder').file('something-inFolder.txt','My content');
zip.finalize();

// NodeJS file content:
    var fs = require('fs');
    var path = require('path');
    var archiver = require('archiver');

  function zipper(archive, settings) {
    return {
        output: null,
        streamToFile(dir) {
            const output = fs.createWriteStream(dir);
            this.output = output;
            archive.pipe(output);

            return this;
        },
        file(location, content) {
            if (settings.location) {
                location = path.join(settings.location, location);
            }
            archive.append(content, { name: location });
            return this;
        },
        folder(location) {
            if (settings.location) {
                location = path.join(settings.location, location);
            }
            return zipper(archive, { location: location });
        },
        finalize() {
            archive.finalize();
            return this;
        },
        onDone(method) {
            this.output.on('close', method);
            return this;
        },
        onError(method) {
            this.output.on('error', method);
            return this;
        }
    };
}

exports.JSzipStream = {
    to(destination) {
        console.log('stream to',destination)
        const archive = archiver('zip', {
            zlib: { level: 9 } // Sets the compression level.
        });
        return zipper(archive, {}).streamToFile(destination);
    }
};
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.