NodeJS - 请求文件并压缩它

时间:2018-02-01 15:58:06

标签: javascript node.js download archive

我目前正在为我的个人网站创建REST API。我想要包含一些下载,我想提供选择多个下载的可能性并将其下载为zip文件。 我的第一种方法很简单:带有网址的数组,请求每个网址,压缩,发送给用户,删除。但是,我认为这种方法太脏了,因为有些东西像溪流似乎非常适合这件事。

现在,我尝试过,目前正在努力解决在不同范围内使用流和事件的基本概念。

以下工作:

const r = request(url, options);
r.on('response', function(res) {
    res.pipe(fs.createWriteStream('./file.jpg'));
});

根据我的理解,r是这个场景中的传入流,我在其上侦听响应事件,一旦发生,我将它传输到我用来写入文件系统的流。

我的第一步是重构这一点,以便更适合我的情况,但我已经在这里失败了:

async function downloadFile(url) {
    return request({ method: 'GET', uri: url });
}

现在我想使用一个调用" downloadFile()"使用不同的URL并使用createWriteStream()再次将所有这些文件保存到磁盘:

const urls = ['https://download1', 'https://download2', 'https://download3'];
urls.forEach(element => {
    downloadFile(element).then(data => {
        data.pipe(fs.createWriteStream('file.jpg'));
    });
});

使用调试器我发现"响应"数据对象中不存在事件 - 可能这已经成为问题了吗?而且,我认为data.body包含我下载文档的字节(在这种情况下为pdf),所以我想知道我是否可以将其流式传输到其他地方?

在阅读了一些stackoveflow线程后,我找到了以下模块:archiver

阅读此主题:Dynamically create and stream zip to client

@dankohn建议采用这样的方法:

archive
  .append(fs.createReadStream(file1), { name: 'file1.txt' })
  .append(fs.createReadStream(file2), { name: 'file2.txt' });

让我假设我需要能够从我的数据对象中提取流来继续。

我在这里走错路还是我得到了一些根本错误的东西?

编辑:lmao感谢您解决我的问题我不知道发生了什么

1 个答案:

答案 0 :(得分:0)

使用archiver似乎是一种有效的方法,但是在将大量数据从Web提供到zip存档时使用流是明智的。否则,整个存档数据需要保存在内存中。

archiver不支持从流中添加文件,但zip-stream可以。为了从网络上阅读流,request会派上用场。

实施例

// npm install -s express zip-stream request

const request = require('request');
const ZipStream = require('zip-stream');
const express = require('express');

const app = express();

app.get('/archive.zip', (req, res) => {
    var zip = new ZipStream()
    zip.pipe(res);

    var stream = request('https://loremflickr.com/640/480')
    zip.entry(stream, { name: 'picture.jpg' }, err => {
        if(err)
            throw err;          
    })

    zip.finalize()
});

app.listen(3000)

更新:使用多个文件的示例

添加一个递归处理zip.entry()回调函数中下一个文件的示例。

app.get('/archive.zip', (req, res) => {
    var zip = new ZipStream()
    zip.pipe(res);

    var queue = [
        { name: 'one.jpg', url: 'https://loremflickr.com/640/480' },
        { name: 'two.jpg', url: 'https://loremflickr.com/640/480' },
        { name: 'three.jpg', url: 'https://loremflickr.com/640/480' }
    ]

    function addNextFile() {
        var elem = queue.shift()
        var stream = request(elem.url)
        zip.entry(stream, { name: elem.name }, err => {
            if(err)
                throw err;
            if(queue.length > 0)
                addNextFile()
            else
                zip.finalize()
        })
    }

    addNextFile()
})
相关问题