Перейти к основному содержимому

Загрузка файлов с использованием потоков Node.js

При работе с большими файлами эффективнее использовать потоки Node.js для их загрузки и передачи. В этом примере показано, как загружать файлы с помощью потоков.

Скрипт использует краулер FileDownload для загрузки файлов с помощью потоков, отслеживания прогресса и сохранения данных в хранилище ключ-значение. При локальной конфигурации данные будут сохранены в виде файлов в директории ./storage/key_value_stores/default.

Run on
import { pipeline, Transform } from 'stream';

import { FileDownload, type Log } from 'crawlee';

// Пример Transform потока, который отслеживает прогресс загрузки.
function createProgressTracker({ url, log, totalBytes }: { url: URL; log: Log; totalBytes: number }) {
let downloadedBytes = 0;

return new Transform({
transform(chunk, _, callback) {
if (downloadedBytes % 1e6 > (downloadedBytes + chunk.length) % 1e6) {
log.info(
`Downloaded ${downloadedBytes / 1e6} MB (${Math.floor((downloadedBytes / totalBytes) * 100)}%) for ${url}.`,
);
}
downloadedBytes += chunk.length;

this.push(chunk);
callback();
},
});
}

// Создаем FileDownload - экземпляр пользовательского краулера, который будет загружать файлы из URL.
const crawler = new FileDownload({
async streamHandler({ stream, request, log, getKeyValueStore }) {
const url = new URL(request.url);

log.info(`Downloading ${url} to ${url.pathname.replace(/\//g, '_')}...`);

await new Promise<void>((resolve, reject) => {
// С помощью события 'response' мы получили заголовки ответа.
stream.on('response', async (response) => {
const kvs = await getKeyValueStore();
await kvs.setValue(
url.pathname.replace(/\//g, '_'),
pipeline(
stream,
createProgressTracker({ url, log, totalBytes: Number(response.headers['content-length']) }),
(error) => {
if (error) reject(error);
},
),
{ contentType: response.headers['content-type'] },
);

log.info(`Downloaded ${url} to ${url.pathname.replace(/\//g, '_')}.`);

resolve();
});
});
},
});

// Список начальных URL для сканирования. Здесь мы используем несколько жестко закодированных URL.
await crawler.addRequests([
'https://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4',
'https://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v',
]);

// Запускаем сканер и ждем, пока он закончится.
await crawler.run();