| 13 | const util = require('util'); |
| 14 | |
| 15 | export async function downloadUrl(dispatch: TaskEventDispatcher, url: string, targetPath: string): Promise<void> { |
| 16 | const { systemProxy, systemProxyString } = await getSystemProxy(); |
| 17 | const filename: string = path.basename(url); |
| 18 | if (fs.existsSync(targetPath) && fs.statSync(targetPath).size > 0) { |
| 19 | return; |
| 20 | } |
| 21 | dispatch({ |
| 22 | message: `Downloading ${url}` |
| 23 | }); |
| 24 | try { |
| 25 | await fsExtra.ensureDir(path.dirname(targetPath)); |
| 26 | const headers: { [key: string]: string } = { |
| 27 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3', |
| 28 | }; |
| 29 | if (systemProxy.http_proxy) { |
| 30 | logger.info("download with proxy" + systemProxyString) |
| 31 | } else { |
| 32 | logger.info("download without proxy") |
| 33 | } |
| 34 | const agentOptions = { |
| 35 | secureProtocol: 'TLSv1_2_method', |
| 36 | }; |
| 37 | const response: Response = await fetch( |
| 38 | url, { |
| 39 | headers, |
| 40 | agent: systemProxy.http_proxy ? new HttpsProxyAgent(systemProxy.http_proxy as string, agentOptions) : undefined, |
| 41 | }); |
| 42 | if (!response.ok) { |
| 43 | throw new Error(`Failed to download from ${url}. Status: ${response.status} ${response.statusText}`); |
| 44 | } |
| 45 | |
| 46 | const totalSize = Number(response.headers.get('content-length')); |
| 47 | const progressBar = new progress('[:bar] :percent :etas', { |
| 48 | complete: '=', |
| 49 | incomplete: ' ', |
| 50 | width: 40, |
| 51 | total: totalSize, |
| 52 | }); |
| 53 | |
| 54 | const finished = util.promisify(stream.finished); |
| 55 | |
| 56 | const bufferStream = new stream.PassThrough(); |
| 57 | const writeStream = fs.createWriteStream(targetPath); |
| 58 | |
| 59 | bufferStream.on('error', (err: any) => { |
| 60 | const msg = `Error with buffer stream: ${err.message}, ${err.stack}` |
| 61 | logger.error(msg); |
| 62 | throw new Error(msg) |
| 63 | }); |
| 64 | |
| 65 | writeStream.on('error', (err: any) => { |
| 66 | const msg = `Error writing to file: ${err.message}, ${err.stack}` |
| 67 | logger.error(msg); |
| 68 | throw new Error(msg) |
| 69 | }); |
| 70 | |
| 71 | response.body!.on('error', (err) => { |
| 72 | const msg = `Error reading from response body: ${err.message}, ${err.stack}` |