2016-07-25 79 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

相關問題