2016-07-25 50 views
2

我有一个Gulp任务,我在ZIP文件中添加大量文件(在一种情况下超过2700个,但在其他一些情况下可能会有几千个)。其代码如下:如何创建一个包含大量文件的Gulp ZIP文件?

const fs = require('fs'); 
const archiver = require('archiver')('zip'); 

let zip = fs.createWriteStream('my-archive.zip'); 
return gulp.src('app/**/*') 
    .pipe(through.obj((file, encoding, cb) => { 
    let pathInZip = '...'; 
    if (!isADirectory(file.path)) { // Do not zip the directory itself 
     archiver.append(fs.createReadStream(file.path), { 
     name: pathInZip, 
     mode: fs.statSync(file.path) 
     }); 
    } 
    cb(null, file); 
    }, cb => { 
    // Now create the ZIP file! 
    archiver.pipe(zip); 
    archiver.finalize(); 
    cb(); 
    })); 

此代码适用于小项目,但是当它与超过2000个文件的交易,我得到以下错误:

events.js:154 
throw er; // Unhandled 'error' event 
^ 

Error: EMFILE: too many open files, open 'd:\dev\app\some\file' 
at Error (native) 

所以我的理解是有2000+在写入ZIP文件之前同时打开的文件不是一个好主意。

如何在不需要打开所有文件的情况下要求编写ZIP文件?

谢谢。

的信息:节点5.5.0/3.8.5 NPM/archiver 1.0.0 /窗口

+1

'archiver.append'接受'callback'作为最后一个参数,也许尝试关闭流呢? – jjm

回答

2

咕嘟咕嘟已经采取了很多你想要做的事情的护理:

  • gulp.src()读取文件内容并为每个文件调用fs.stat()。然后它将file.contentsfile.stat存储在它发出的vinyl-file对象上。
  • 它通过使用graceful-fs包执行此操作,该包在出现EMFILE错误时自动退避,并在另一个文件关闭时重试。这可以防止您遇到的“打开的文件过多”问题。

不幸的是你不采取任何这些,因为优势:

  • 你让显式调用fs.statSync()fs.createReadStream()。因为gulp已经为你做了这件事,所以真的没有必要。您有效地读取每个文件两次(并创建该过程中文件描述符数量的两倍)。
  • 通过直接使用fs模块,您无法防范“太多打开的文件”问题,从而规避了吞噬EMFILE的内置保护。

我已经重写了您的代码以充分利用gulp的功能。我也试图让它更具吸引力,例如,通过使用gulp-filter摆脱目录:

const gulp = require('gulp'); 
const fs = require('graceful-fs'); 
const archiver = require('archiver')('zip'); 
const through = require('through2'); 
const filter = require('gulp-filter'); 

gulp.task('default',() => { 
    var zip = fs.createWriteStream('my-archive.zip'); 
    archiver.pipe(zip); 
    return gulp.src('app/**/*') 
    .pipe(filter((file) => !file.stat.isDirectory())) 
    .pipe(through.obj((file, encoding, cb) => { 
     var pathInZip = '...'; 
     archiver.append(file.contents, { 
     name: pathInZip, 
     mode: file.stat 
     }); 
     cb(null, file); 
    }, cb => { 
     zip.on('finish', cb); 
     archiver.finalize(); 
    })); 
}); 
+0

非常感谢,不仅对于给出正确的代码,而且对于您的完整解释! – romaintaz

相关问题