Подтвердить что ты не робот

Получение двоичного содержимого в node.js с помощью http.request

Я хотел бы получить двоичные данные из запроса https.

Я нашел похожий вопрос, в котором используется метод запроса " Получение бинарного содержимого в Node.js с использованием запроса" - он говорит, что установка кодировки на ноль должна работать, но это не так.

options = {
    hostname: urloptions.hostname,
    path: urloptions.path,
    method: 'GET',
    rejectUnauthorized: false,
    encoding: null
};

req = https.request(options, function(res) {
    var data;
    data = "";
    res.on('data', function(chunk) {
        return data += chunk;
    });
    res.on('end', function() {
        return loadFile(data);
    });
    res.on('error', function(err) {
        console.log("Error during HTTP request");
        console.log(err.message);
    });
})

Редактировать: установка кодировки в "двоичный" также не работает

4b9b3361

Ответ 1

Принятый ответ не работал у меня (т.е. установил кодировку в двоичный файл), даже пользователь, который задал вопрос о том, что он не работает.

Здесь то, что сработало для меня, взято из: http://chad.pantherdev.com/node-js-binary-http-streams/

http.get(url.parse('http://myserver.com:9999/package'), function(res) {
    var data = [];

    res.on('data', function(chunk) {
        data.push(chunk);
    }).on('end', function() {
        //at this point data is an array of Buffers
        //so Buffer.concat() can make us a new Buffer
        //of all of them together
        var buffer = Buffer.concat(data);
        console.log(buffer.toString('base64'));
    });
});

Изменить: Обновить ответ после предложения Semicolon

Ответ 2

Вам нужно установить кодировку в ответ, а не запросить:

req = https.request(options, function(res) {
    res.setEncoding('binary');

    var data = [ ];

    res.on('data', function(chunk) {
        data.push(chunk);
    });
    res.on('end', function() {
        var binary = Buffer.concat(data);
        // binary is your data
    });
    res.on('error', function(err) {
        console.log("Error during HTTP request");
        console.log(err.message);
    });
});

Вот полезный ответ: Написание изображения на локальный сервер

Ответ 3

Работа на NodeJS 6.10 (и 8.10, протестирована в феврале 2019 года) в среде AWS Lambda, ни одно из вышеперечисленных решений для меня не работает.

То, что сработало для меня, было следующим:

https.get(opt, (res) => {
    res.setEncoding('binary');
    let chunks = [];

    res.on('data', (chunk) => {
        chunks.push(Buffer.from(chunk, 'binary'));
    });

    res.on('end', () => {
        let binary = Buffer.concat(chunks);
        // binary is now a Buffer that can be used as Uint8Array or as
        // any other TypedArray for data processing in NodeJS or 
        // passed on via the Buffer to something else.
    });
});

Обратите внимание на res.setEncoding('binary'); и Buffer.from(chunk, 'binary') строки. Один устанавливает кодировку ответа, а другой создает объект Buffer из строки, предоставленной в кодировке, указанной ранее.

Ответ 4

Перт Йохансон. Я хотел бы прокомментировать, чтобы поблагодарить вас за то, что вы спасли меня от рекурсивного цикла, за который я весь день рвал волосы, а затем читал (невероятно бесполезные) документы по узлам на этом, снова и снова. Найдя ваш ответ, я пошел копаться в документах, и я даже не могу найти метод res.setEncoding документированный где-либо! Это просто показано как часть двух примеров, в которых они вызывают res.setEncoding('utf8'); Где ты это нашел или как ты это понял !?

Поскольку у меня недостаточно репутации, чтобы комментировать, я, по крайней мере, внесу что-то полезное в свой ответ: ответ Пярта Йохансона для меня сработал на 100%, я просто немного подправил его для своих нужд, потому что я использую его для загрузки и Проверьте сценарий, размещенный на моем сервере (и скомпилированный с помощью nwjc), используя nw.Window.get().evalNWBin() в NWJS 0.36.4/Node 11.11.0:

let opt = {...};
let req = require('https').request(opt, (res) => {
  // server error returned
  if (200 !== res.statusCode) {
    res.setEncoding('utf8');
    let data = '';
    res.on('data', (strData) => {
      data += strData;
    });
    res.on('end', () => {
      if (!res.complete) {
        console.log('Server error, incomplete response: ' + data);
      } else {
        console.log('Server error, response: ' + data);
      }
    });
  }
  // expected response
  else {
    res.setEncoding('binary');
    let data = [];
    res.on('data', (binData) => {
      data.push(Buffer.from(binData, 'binary'));
    });
    res.on('end', () => {
      data = Buffer.concat(data);
      if (!res.complete) {
        console.log('Request completed, incomplete response, ' + data.length + ' bytes received);
      } else {
        console.log('Request completed, ' + data.length + ' bytes received');
        nw.Window.get().evalNWBin(null, data);
      }
    });
  }
};

Изменение: PS Я разместил это на всякий случай, если кто-то хотел знать, как обрабатывать недвоичный ответ - мой фактический код идет немного глубже и проверяет заголовок типа содержимого ответа для анализа JSON (предполагаемый сбой, то есть 400, 401, 403) или HTML (неожиданный сбой, т.е. 404 или 500)

Ответ 5

  1. Не setEncoding() метод setEncoding(), потому что по умолчанию кодировка не назначена, и данные потока будут возвращены как объекты Buffer
  2. Вызовите Buffer.from() в on.data обратного вызова on.data чтобы преобразовать значение chunk в объект Buffer.
http.get('my_url', (response) => {
  const chunks = [];
  response.on('data', chunk => chunks.push(Buffer.from(chunk))) // Converte 'chunk' to a 'Buffer' object.
    .on('end', () => {
      const buffer = Buffer.concat(chunks);
      console.log(buffer.toString('base64'));
    });
});

Ответ 6

Как и другим, мне нужно было обрабатывать фрагменты двоичных данных из HTTP-ответа Node.js (он же http.IncomingMessage).

Ни один из существующих ответов действительно не работал для моего проекта Electron 6 (в комплекте с Node.js 12.4.0, на момент публикации), кроме Pärt Johanson answer и его вариантов.

Тем не менее, даже при таком решении куски всегда поступали в обработчик response.on('data', ondata) как объекты string (а не как ожидаемые и желаемые объекты Buffer). Это повлекло за собой дополнительное преобразование с Buffer.from(chunk, 'binary'). Я получал строки независимо от того, явно ли я указал двоичное кодирование с помощью response.setEncoding('binary') или response.setEncoding(null).

Единственный способ получить оригинальные чанки Buffer - передать response в экземпляр stream.Writable, где я предоставляю собственный метод write:

const https = require('https');
const { Writable } = require('stream');

async function getBinaryDataAsync(url) {
  // start HTTP request, get binary response
  const { request, response } = await new Promise((resolve, reject) => {
    const request = https.request(url, { 
      method: 'GET', 
        headers: { 
          'Accept': 'application/pdf', 
          'Accept-Encoding': 'identity'
        }        
      }
    );

    request.on('response', response => 
      resolve({request, response}));
    request.on('error', reject);
    request.end();
  });

  // read the binary response by piping it to stream.Writable
  const buffers = await new Promise((resolve, reject) => {

    response.on('aborted', reject);
    response.on('error', reject);

    const chunks = [];

    const stream = new Writable({
      write: (chunk, encoding, notifyComplete) => {
        try {
          chunks.push(chunk);
          notifyComplete();      
        }
        catch(error) {
          notifyComplete(error);      
        }
      }
    });

    stream.on('error', reject);
    stream.on('finish', () => resolve(chunks));
    response.pipe(stream);
  });

  const buffer = Buffer.concat(buffers);
  return buffer.buffer; // as ArrayBuffer
}

async function main() {
  const arrayBuff = await getBinaryDataAsync('https://download.microsoft.com/download/8/A/4/8A48E46A-C355-4E5C-8417-E6ACD8A207D4/VisualStudioCode-TipsAndTricks-Vol.1.pdf');
  console.log(arrayBuff.byteLength);
};

main().catch(error => console.error(error));

Обновленный, как оказалось, это поведение проявляется только для нашего сервера веб-API. Таким образом, response.on('data') на самом деле хорошо работает для примера URL, который я использую в приведенном выше фрагменте кода, и поток для него не нужен. Это странно, хотя это специфично, я исследую это дальше.