dynamic创build并将zip压缩到客户端

我正在使用NodeJs(w / express),我正尝试将一个zip文件传回客户端。 zip中包含的文件不在文件系统中,而是dynamic创build。 我想将文件内容传输到压缩文件,然后将压缩文件传输回客户端。

IE我希望客户端收到:

tmp.zip --> 1.txt --> 2.txt --> 3.txt 

其中1,2,3.txt是dynamic创build的,并stream式传输到zip文件。 这可能吗?

Archiver有一个附加方法,可以让您将文本保存为文件。 要将这些数据“stream式传输”给用户,只需将其传输到HTTP响应对象即可。

 var Http = require('http'); var Archiver = require('archiver'); Http.createServer(function (request, response) { // Tell the browser that this is a zip file. response.writeHead(200, { 'Content-Type': 'application/zip', 'Content-disposition': 'attachment; filename=myFile.zip' }); var zip = Archiver('zip'); // Send the file to the page output. zip.pipe(response); // Create zip with some files. Two dynamic, one static. Put #2 in a sub folder. zip.append('Some text to go in file 1.', { name: '1.txt' }) .append('Some text to go in file 2. I go in a folder!', { name: 'somefolder/2.txt' }) .file('staticFiles/3.txt', { name: '3.txt' }) .finalize(); }).listen(process.env.PORT); 

这将创build一个带有两个文本文件的zip文件。 访问此页面的用户将看到文件下载提示。

解决scheme: express.js,wait.for,zip-stream

 app.get('/api/box/:box/:key/download', function (req, res) { var wait = require('wait.for'); var items = wait.for(function (next) { BoxItem.find({box: req.Box}).exec(next) }); res.set('Content-Type', 'application/zip'); res.set('Content-Disposition', 'attachment; filename=' + req.Box.id + '.zip'); var ZipStream = require('zip-stream'); var zip = new ZipStream(); zip.on('error', function (err) { throw err; }); zip.pipe(res); items.forEach(function (item) { wait.for(function (next) { var path = storage.getItemPath(req.Box, item); var source = require('fs').createReadStream(path); zip.entry(source, { name: item.name }, next); }) }); zip.finalize(); }); 

是的,这是可能的。 我build议看看Streams Playground ,以了解节点stream如何工作。

核心zlib库中的zip压缩似乎不支持多个文件。 如果你想使用tar-gzip,你可以使用node-tar对其进行tar 。 但是,如果你想要的ZIP, adm-zip看起来像最好的select。 另一种可能是节点归档 。

更新:

此示例显示如何使用支持stream的Archiver。 只需将fs.createReadStreamreplace为dynamic创build的stream,并将outputstream转换为Express的res而不是fs.createWriteStream

 var fs = require('fs'); var archiver = require('archiver'); var output = fs.createWriteStream(__dirname + '/example-output.zip'); var archive = archiver('zip'); output.on('close', function() { console.log('archiver has been finalized and the output file descriptor has closed.'); }); archive.on('error', function(err) { throw err; }); archive.pipe(output); var file1 = __dirname + '/fixtures/file1.txt'; var file2 = __dirname + '/fixtures/file2.txt'; archive .append(fs.createReadStream(file1), { name: 'file1.txt' }) .append(fs.createReadStream(file2), { name: 'file2.txt' }); archive.finalize(function(err, bytes) { if (err) { throw err; } console.log(bytes + ' total bytes'); });