【问题标题】:Node.js and Requestjs: Pipe a Transform stream to Request.js as a file for uploadNode.js 和 Requestjs:通过管道将转换流作为文件上传到 Request.js
【发布时间】:2016-02-22 21:28:22
【问题描述】:

我正在使用 node-archiver (https://github.com/archiverjs/node-archiver) 在内存上创建一个 zip 文件。 使用归档器的管道功能,我将所有内容通过管道传输到转换流。 如果需要,我可以将此流通过管道传输到文件,但我想让 Request (https://github.com/request) 读取此流,因此我不必访问文件系统。

下面,我的转换流称为bridge。我没有对 Transform 做任何特别的事情(我相信它也可以是 PassThrough 流)。

var archive = archiver('zip');
archive.pipe(bridge);
var r = request.post(url, function(err, res, body){ .... }
var form = r.form();
form.append('token', <some token>);
form.append('file', bridge, { "filename" : "package.zip", "contentType" : "application/zip" });
archive.append(<some string>, { "name": <some file name> });
archive.finalize();

这不起作用(似乎file 部分为空)。但是,如果我将桥转换流通过管道传输到文件写入流——并且在流完成后——我在表单文件操作中创建一个读取流到该文件,它就可以工作。当然,因为现在我有一个完整的文件,request 可以读取它(这里我不需要桥,只需要常规的fs 流)

bridge.pipe(fs.createWriteStream(<myfile>));
var archive = archiver('zip');
archive.pipe(bridge);
bridge.on("finish", function(){
    var r = request.post(url, function(err, res, body){ .... }
    var form = r.form();
    form.append('token', <some token>);
    form.append('file', fs.createReadStream(<myfile>), { "filename" : "package.zip", "contentType" : "application/zip" });

}
archive.append(<some string>, { "name": <some file name> });    
archive.finalize();

我想知道request 是否要求读取流是文件流——以及我在这里可能做错什么。

【问题讨论】:

    标签: node.js stream requestjs node-archiver


    【解决方案1】:

    我有一个类似的问题,发现问题既不是 nodejs 也不是 requestjs。

    这是 HTTP 的限制。您无法上传没有已知内容长度的文件,在转换完成之前您无法从转换中知道该长度。看到这个:HTTP POST: content-length header required?

    解决此问题的唯一方法是一次上传小块,并带有可读事件。不过,这需要您的目标 API 允许分块或分段上传。

    【讨论】:

    • 那是我的恐惧。因此,尽管 Request 接受一个流 (fs.createReadStream),但它从 readstream 对象中获取它的内容长度。我想知道是否有可能在完成时获取存档器内容长度,然后为请求设置此标头。似乎可以通过侦听归档器上的关闭事件(类似于 stackoverflow.com/a/30882016/2020565 和/或使用归档器指针 archiverjs.com/docs/Archiver.html#pointer 来累积总字节数。
    • 在发起 HTTP 请求之前,您仍然需要知道内容长度。所以我看不出这有什么帮助。您可以做的一件事是创建一个具有足够大的 highWaterMark 的直通流,以将您的 zip 存储在内存中,然后上传该新流。在我的情况下这是不可能的,因为我期望流可能是 10GB 的数量级。
    • 也许可以“将归档器管道化为空”,获取内容大小并然后重做操作,这次将内容长度设置为长度获取的数据。 显然,这意味着执行两次归档操作,但无需将所有内容存储在内存中。有这个替代方案会很好。我会试试看。
    猜你喜欢
    • 2023-03-24
    • 2017-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-17
    相关资源
    最近更新 更多