我有一个Gulp任务,我在ZIP文件中添加了大量文件(在一种情况下超过2700个,但在其他情况下可能有几千个)。代码如下:
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)
所以我理解在将这些文件写入ZIP之前同时打开2000多个文件并不是一个好主意。
如何在不需要打开所有文件的情况下询问ZIP文件?
感谢。
有关信息:节点5.5.0 / npm 3.8.5 / archiver 1.0.0 / windows
答案 0 :(得分:2)
Gulp已经处理了你要做的很多事情:
gulp.src()
读取文件内容并对每个文件进行fs.stat()
调用。然后,它会将file.contents
和file.stat
存储在它发出的vinyl-file
个对象上。graceful-fs
包来实现的,该包在EMFILE错误的情况下自动退避,在另一个文件关闭时重试。这可以防止"过多的打开文件"你遇到的问题。不幸的是,你没有利用其中任何一个因为:
fs.statSync()
和fs.createReadStream()
。因为gulp已经为你做了这件事,所以真的没有必要。您有效地读取每个文件两次(并在此过程中创建两倍的文件描述符)。fs
模块来避免吞噬对EMFILE的内置保护,该模块没有任何防范过多的打开文件"太多的打开文件&#34 ;问题。我已经重写了您的代码以利用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();
}));
});