【问题标题】:Find the content-length of the stream before uploading the file or writing the file on network在上传文件或在网络上写入文件之前查找流的内容长度
【发布时间】:2019-08-19 20:39:01
【问题描述】:

我正在读取文件,对其进行压缩和加密,然后在网络上上传/写入。但我需要知道结束流的内容长度(通过读取、压缩、加密后返回的流)才能发出发布请求。

let zlib = zlib.createGzip(),
   encrypt = crypto.cipherIV(....),
    input = fs.createReadStream('file.jpg');
function zipAndEncrypt(){
   let stream = readStream.pipe( zlib).pipe( encrypt );
   let options = {
     "stream_length":0,
     headers: { "content-type": 'image/jpeg',
                "content-length": '123456', // need to get this length 
          .....
     }
    }

// post the stream
needle( 'post', url, stream, options )
   .then( resp => { console.log( "file length", resp.body.length);})
   .catch( err => {})
}

如果我在标题中输入正确的内容长度(在这种情况下我知道长度),上面的代码就可以工作。所以我需要找到流的长度。

到目前为止,我的长度达到了:

  let chunk = [], conLength;
  stream.on( 'data', ( data ) => {
            chunk.push( data );
        } )
        .on( 'end', () => {
         conLength = Buffer.concat( chunk ).length; 
        } );

但是post请求失败,SOCKET挂断错误。

看起来流已耗尽或消耗,因为在使用上面的代码找到长度后它没有发出“数据”事件。

尝试了 stream.resume()。但没有任何效果。您能否建议如何在不消耗流的情况下找到流的长度。

【问题讨论】:

  • 没有内容长度就不能发送吗?
  • 如果你需要加密打包后的文件大小,你需要先做这个,然后再发布到服务器。您可以将流存储在内存中,等到文件被压缩,然后获取文件大小&您可以使用正确的内容长度标头执行您的发布请求
  • 你看到我的回答了吗? @蒂姆
  • @MarcosCasagrande 我检查了你的答案。谢谢你。把它写在磁盘上然后找到长度是个好主意。

标签: javascript node.js stream pipeline needle.js


【解决方案1】:

如果您需要发送内容长度,知道它的唯一方法是在文件被压缩和加密之后。

因此,您的解决方案有效,但前提是您发送缓冲区而不是流,因为您已经使用了流中的所有数据。既然你已经在内存中拥有了所有的块,你不妨发送它。

let chunk = [];

stream.on('data', data => chunk.push(data))
.on('end', () => {
    const buffer = Buffer.concat(chunk);
    const conLength = buffer.length;
    // Execute the request here, sending the whole buffer, not the stream
    needle(/*...*/)
});

但是,如果您的文件太大,则需要对其进行流式传输,否则您将达到内存不足,一个简单的解决方法,只需一点开销,就是将其通过管道传输到一个临时文件,然后发送该文件.这样您就可以在执行请求、访问stream.bytesWritten 属性或使用fs.lstat 之前知道文件大小。

function zipAndEncrypt(input) {
    const gzip = zlib.createGzip();
    const encrypt = crypto.createCipheriv(algo, key, iv),

    const stream = input.pipe(gzip).pipe(encrypt);


    const fileName = tmpFileName();
    const file = fs.createWriteStream(fileName)
    stream
        .pipe(file)
        .on('finish', () => {
            let options = {
                "stream_length": 0,
                headers: {
                    "content-type": 'image/jpeg',
                    "content-length": file.bytesWritten
                }
            }

            const readStream = fs.createReadStream(fileName);

            // post the stream
            needle('post', url, readStream, options)
                .then(resp => {
                    console.log("file length", resp.body.length);
                })
                .catch(err => {})
                .finally(() => {
                    // Remove the file from disk
                });
        })

}

【讨论】:

    猜你喜欢
    • 2023-04-01
    • 1970-01-01
    • 2012-01-19
    • 2014-09-28
    • 1970-01-01
    • 1970-01-01
    • 2017-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多