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 - 파일을 다운로드하는 사용자 지정 크롤러 인스턴스.
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();