Запрос скрипта Node.js, использующий заголовок HTTP Range, приводит к большему количеству байтов, чем запрошено.
Я пытаюсь написать скрипт Node.js, который принимает URL-адрес (для загрузки файла), указанный в командной строке. Используя заголовок запроса HTTP Range, скрипт загружает файл с настраиваемым количеством блоков и размером блока, а затем записывает в выходной файл в правильном порядке байтов.
В настоящее время мы стремимся достичь этого с помощью 2 блоков по 1 МБ (1 048 576 байт), что в общей сложности составляет 2 МБ (2 097 152 B).
Текущая проблема, с которой я сталкиваюсь: либо выполняется, либо я просто понимаю, что мой сценарий записывает ~ 1 800 000 байт для каждого запроса, что в итоге составляет 3 764 942 байта. Не уверены, откуда эти дополнительные байты?
Это из-за ошибки, которую я пропустил в этом скрипте, или из-за издержек из используемой библиотеки запросов, может быть, или я что-то упустил в преобразовании Mib в байты?
- Содержимое файла в настоящее время в значительной степени не имеет значения, если правильное количество байтов находится в правильном порядке.
- Если свернуть тестовый 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-обещания 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)
});
}
0 ответов
Проблема в том, что вы добавляете весь объект ответа, а не его содержимое / тело.
Вы можете использовать ответ data
событие, чтобы получить контент, а затем добавить его в файл.