在上传文件或网络写入文件之前找到流的 content-length
Find the content-length of the stream before uploading the file or writing the file on network
我正在读取文件,压缩并加密它,然后 uploading/writing 在网络上。但我需要知道结束流(通过读取、压缩、加密后返回的流)的 content-length 才能发出 post 请求。
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 => {})
}
如果我在 headers 中输入正确的内容长度(在这种情况下我知道长度),以上代码就可以工作。所以我需要找到流的长度。
到目前为止,我达到了长度:
let chunk = [], conLength;
stream.on( 'data', ( data ) => {
chunk.push( data );
} )
.on( 'end', () => {
conLength = Buffer.concat( chunk ).length;
} );
但是post请求失败,SOCKET挂断错误
看起来流被耗尽或消耗了,因为它在使用上面的代码找到长度后没有发出 'data' 事件。
已尝试 stream.resume()。但没有任何效果。您能否建议如何在不消耗流的情况下找到流的长度。
如果您需要发送内容长度,唯一知道它的方法是在文件被压缩和加密之后。
因此,您的解决方案有效,但前提是您发送缓冲区而不是流,因为您已经使用了流中的所有数据。并且由于您已经在内存中拥有所有块,所以您不妨发送它。
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
});
})
}
我正在读取文件,压缩并加密它,然后 uploading/writing 在网络上。但我需要知道结束流(通过读取、压缩、加密后返回的流)的 content-length 才能发出 post 请求。
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 => {})
}
如果我在 headers 中输入正确的内容长度(在这种情况下我知道长度),以上代码就可以工作。所以我需要找到流的长度。
到目前为止,我达到了长度:
let chunk = [], conLength;
stream.on( 'data', ( data ) => {
chunk.push( data );
} )
.on( 'end', () => {
conLength = Buffer.concat( chunk ).length;
} );
但是post请求失败,SOCKET挂断错误
看起来流被耗尽或消耗了,因为它在使用上面的代码找到长度后没有发出 'data' 事件。
已尝试 stream.resume()。但没有任何效果。您能否建议如何在不消耗流的情况下找到流的长度。
如果您需要发送内容长度,唯一知道它的方法是在文件被压缩和加密之后。
因此,您的解决方案有效,但前提是您发送缓冲区而不是流,因为您已经使用了流中的所有数据。并且由于您已经在内存中拥有所有块,所以您不妨发送它。
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
});
})
}