new Downloader
Posted acmeryblog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了new Downloader相关的知识,希望对你有一定的参考价值。
/**
- Simple Node.js Download Client.
- Only support http and https.
- Only support get method.
*/
- Only support get method.
import * as path from "path";
import * as fs from "fs";
import { URL } from "url";
import * as http from "http";
import * as https from "https";
export interface IDownloaderItem {
src: URL;
dest: URL;
fileName?: string;
}
export class Downloader {
public downloadFile(item: IDownloaderItem): any {
let error: Error | null | undefined;
if (item.src.protocol === "http:") {
return this.httpDownload(item);
} else if (item.src.protocol === "https:") {
return this.httpsDownload(item);
} else {
error = new Error(`Downloader is not support ${item.src.protocol.split(":")[0]} protocol!`);
}
if (!(error === null || error === undefined)) {
console.error(error.message);
return;
}
}
private httpDownload(item: IDownloaderItem): any {
let error: Error | null | undefined;
let saveFilePath: string | null | undefined;
http.get(item.src, (res) => {
if (res.statusCode === 200) {
saveFilePath = path.join(item.dest.pathname, this.getSaveFileName(item, res));
let totalFileSize = this.getDownloadFileSize(res);
console.log(`Starting download.
SavePath:${saveFilePath}.
TotalSize: ${this.getHumanFileSize(totalFileSize)}. `);
let writeStream = fs.createWriteStream(saveFilePath);
res.pipe(writeStream);
writeStream.on('close', () => {
console.log('Finished download.');
return saveFilePath;
});
} else if (res.statusCode === 302) {
let location = res.headers['location'];
console.log(`It's a redirect download: ${location}`);
if (!(location === undefined)) {
item.src = new URL(location);
}
this.downloadFile(item);
} else {
error = new Error('Request Failed. ' + `Status Code: ${res.statusCode}`);
}
if (!(error === null || error === undefined)) {
console.error(error.message);
res.resume();
return;
}
});
}
private httpsDownload(item: IDownloaderItem): any {
let error: Error | null | undefined;
let saveFilePath: string | null | undefined;
https.get(item.src, (res) => {
if (res.statusCode === 200) {
saveFilePath = path.join(item.dest.pathname, this.getSaveFileName(item, res));
let totalFileSize = this.getDownloadFileSize(res);
console.log(`Starting download.
SavePath:${saveFilePath}.
TotalSize: ${this.getHumanFileSize(totalFileSize)}. `);
fs.mkdirSync(item.dest.pathname, { recursive: true });
let writeStream = fs.createWriteStream(saveFilePath);
res.pipe(writeStream);
writeStream.on('close', () => {
console.log('Finished download.');
return saveFilePath;
});
} else if (res.statusCode === 302) {
let location = res.headers['location'];
console.log(`It's a redirect download: ${location}`);
if (!(location === undefined)) {
item.src = new URL(location);
}
this.downloadFile(item);
} else {
error = new Error('Request Failed. ' + `Status Code: ${res.statusCode}`);
}
if (!(error === null || error === undefined)) {
console.error(error.message);
res.resume();
return;
}
});
}
private getDownloadFileSize(res: http.IncomingMessage): number {
let contentLength = res.headers['content-length'];
if (contentLength === null || contentLength === undefined) {
return 0;
} else {
return Number(contentLength);
}
}
private getHumanFileSize(fileSize: number) {
if (fileSize < 1024) {
return `${fileSize} B`;
} else if (fileSize < 1024 * 1024) {
return `${(fileSize / (1024)).toFixed(2)} KB`;
} else if (fileSize < 1024 * 1024 * 1024) {
return `${(fileSize / (1024 * 1024)).toFixed(2)} MB`;
} else if (fileSize < 1024 * 1024 * 1024 * 1024) {
return `${(fileSize / (1024 * 1024 * 1024)).toFixed(2)} GB`;
} else if (fileSize < 1024 * 1024 * 1024 * 1024 * 1024) {
return `${(fileSize / (1024 * 1024 * 1024 * 1024)).toFixed(2)} TB`;
} else {
return `${fileSize} B`;
}
}
private getSaveFileName(item: IDownloaderItem, res: http.IncomingMessage): string {
if (!(item.fileName === null
|| item.fileName === undefined
|| item.fileName.trim().length === 0)) {
return item.fileName.trim();
}
return this.getOriginalFileName(item, res);
}
private getOriginalFileName(item: IDownloaderItem, res: http.IncomingMessage): string {
let fileName: string;
// Get orgion filename by headers["content-disposition"].
if (!(res.headers["content-disposition"] === null
|| res.headers["content-disposition"] === undefined
|| res.headers["content-disposition"].split("filename=").length === 1)) {
fileName = res.headers["content-disposition"].split("filename=")[1].trim();
if (fileName.length > 0) {
return fileName;
}
}
// Get orgion filename by url address.
if (!(item.src.pathname === null
|| item.src.pathname === undefined
|| item.src.pathname.split("/").length === 1)) {
fileName = item.src.pathname.split("/")[item.src.pathname.split("/").length - 1].trim();
if (fileName.length > 0) {
return fileName;
}
}
// Get orgion filename by Date.
let date = new Date();
fileName = date.getFullYear().toString()
+ date.getMonth().toString()
+ date.getDay().toString()
+ date.getHours().toString()
+ date.getMinutes().toString()
+ date.getSeconds().toString()
+ date.getMilliseconds().toString()
+ ".tmp";
return fileName;
}
}
以上是关于new Downloader的主要内容,如果未能解决你的问题,请参考以下文章