Определите длину содержимого потока перед загрузкой файла или записью файла в сеть - PullRequest
0 голосов
/ 29 марта 2019

Я читаю файл, архивирую и шифрую его, а затем загружаю / пишу по сети.Но мне нужно знать длину содержимого конечного потока (поток, возвращаемый после прохождения через чтение, zip, шифрование), чтобы сделать запрос на публикацию.

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; 
        } );

Но почтовый запрос не выполняется, ошибка зависания SOCKET.

Похоже, что поток истощается или потребляется, так как он не генерирует событие «data» после определения длины с помощью приведенного выше кода.

Пробовал stream.resume ().Но ничего не работает.Не могли бы вы предложить, как найти длину потока, не потребляя поток.

1 Ответ

0 голосов
/ 29 марта 2019

Если вам нужно отправить длину контента, единственный способ узнать это - после того, как файл был заархивирован и зашифрован.

Итак, ваше решение работает, но только если вы отправляете буфер ине поток, потому что вы уже использовали все данные из потока.И так как у вас уже есть все фрагменты в памяти, вы также можете отправить его.

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
                });
        })

}
...