Запрос скрипта Node.js с использованием заголовка HTTP Range приводит к большему количеству байтов, чем запрошено.

Я пытаюсь написать сценарий Node.js, который принимает URL-адрес (для загрузки файла), указанный в командной строке. Используя заголовок запроса HTTP Range, сценарий загружает файл в виде настраиваемого количества фрагментов и размера фрагмента, а затем записывает в выходной файл в правильном порядке байтов.

В настоящее время мы пытаемся добиться этого с помощью 2 фрагментов по 1 МБ (1 048 576 байт), что в сумме составляет 2 МБ (2 097 152 Б).

Текущая проблема, с которой я сталкиваюсь либо при выполнении, либо, насколько я понимаю, заключается в том, что мой скрипт записывает ~ 1 800 000 байтов для каждого запроса, что в сумме составляет 3 764 942 байта. Не знаете, откуда берутся эти дополнительные байты?

Возможно, это связано с ошибкой, которую я пропустил в этом скрипте, или с накладными расходами из библиотеки запросов, используемой, или я что-то упустил в преобразовании Mib в Bytes?

  • Содержимое файла в настоящее время в значительной степени не имеет значения, если правильное количество байтов находится в правильном порядке.
  • Скручивание тестового URL-адреса с заголовком диапазона, установленным на фрагменты 1 МБ, а затем добавление в файл приводит к приближению к ожидаемому общему количеству байтов. curl 'https://eloquentjavascript.net/Eloquent_JavaScript.pdf' -i -H "Range: bytes=0-2097152" => 2097435 B-файл
  • Я запускаю эту команду в терминале node index.js --url='https://eloquentjavascript.net/Eloquent_JavaScript.pdf' --file='newfile.txt' --chunks 2
  • Использование Node v10.12.0, minimist v1.2.0 и request-promise v4.2.2

Весь сценарий ниже:

'use strict';

const argv = require('minimist')(process.argv.slice(2), {
    default: {
        file: 'output.txt',
        MiB: 1,
        chunks: 4
    }
});
const fs = require('fs');
const request = require('request-promise');

// Source URL must be specified through command line option.
if (!argv.url) throw Error('Source URL is required!');

const options = {
    method: 'GET',
    uri: argv.url
}

const determineChunkRange = (step) => {
    // 1 Mib = 1,048,576 B.
    // Only 1 MiB chunks are downloaded.
    const chunkSize = argv.MiB * 1048576;
    const startOfRange = step === 0 ? 0 + ((chunkSize * step)) : 1 + ((chunkSize * step));
    const endOfRange = startOfRange + chunkSize;

    return {'Range': `bytes=${startOfRange}-${endOfRange}`}
}

const getOptions = (step) => {
    options.headers = determineChunkRange(step);

    return options;
}

const addDataToFile = (data) => {
    try {
        fs.appendFileSync(argv.file, data);
        console.log("Data written to file.");
    } catch (err) {
        console.log(`Error appending to ${argv.file}`, err);
    }
}

// Create or Replace file with specific filename.
fs.writeFileSync(argv.file, '');
console.log("Successfully created new file.");

// Make specified number of requests.
for (let i = 0; i < argv.chunks; i++) {
    const options = getOptions(i);

    // make request to specified URL.
    request(options)
        .then(response => {
            console.log(i, options)
            addDataToFile(response)
        })
        .catch(error => {
            console.log(`Error making request to ${argv.url}`, error)
        });
}

person TXRedking    schedule 10.12.2018    source источник
comment
Вы уверены, что ответ содержит только файл? зарегистрируйте ответ, прежде чем записывать его в файл.   -  person yeya    schedule 12.09.2019


Ответы (1)


Проблема в том, что вы добавляете весь объект ответа, а не его содержимое/тело.

Вы можете использовать событие data ответа, чтобы получить содержимое, а затем добавить его в файл.

person AlexG    schedule 21.01.2020