11import fetch from "node-fetch" ;
22import * as fs from "fs" ;
3+ import * as stream from "stream" ;
4+ import * as util from "util" ;
35import { strict as assert } from "assert" ;
46import { NestedError } from "ts-nested-error" ;
57
8+ const pipeline = util . promisify ( stream . pipeline ) ;
9+
610class DownloadFileError extends NestedError { }
711
812/**
@@ -29,25 +33,19 @@ export async function downloadFile(
2933 const totalBytes = Number ( res . headers . get ( 'content-length' ) ) ;
3034 assert ( ! Number . isNaN ( totalBytes ) , "Sanity check of content-length protocol" ) ;
3135
32- let readBytes = 0 ;
33-
3436 console . log ( "Downloading file of" , totalBytes , "bytes size from" , url , "to" , destFilePath ) ;
3537
36- // Here reject() may be called 2 times. As per ECMAScript standard, 2-d call is ignored
37- // https://tc39.es/ecma262/#sec-promise-reject-functions
38-
39- return new Promise < void > ( ( resolve , reject ) => res . body
40- . on ( "data" , ( chunk : Buffer ) => {
41- readBytes += chunk . length ;
42- onProgress ( readBytes , totalBytes ) ;
43- } )
44- . on ( "error" , err => reject (
45- new DownloadFileError ( `Read-stream error, read bytes: ${ readBytes } ` , err )
46- ) )
47- . pipe ( fs . createWriteStream ( destFilePath , { mode : destFilePermissions } ) )
48- . on ( "error" , err => reject (
49- new DownloadFileError ( `Write-stream error, read bytes: ${ readBytes } ` , err )
50- ) )
51- . on ( "close" , resolve )
52- ) ;
38+ let readBytes = 0 ;
39+ res . body . on ( "data" , ( chunk : Buffer ) => {
40+ readBytes += chunk . length ;
41+ onProgress ( readBytes , totalBytes ) ;
42+ } ) ;
43+
44+ const destFileStream = fs . createWriteStream ( destFilePath , { mode : destFilePermissions } ) ;
45+
46+ await pipeline ( res . body , destFileStream ) . catch ( DownloadFileError . rethrow ( "Piping file error" ) ) ;
47+ return new Promise < void > ( resolve => {
48+ destFileStream . on ( "close" , resolve ) ; // details on workaround: https://github.com/rust-analyzer/rust-analyzer/pull/3092#discussion_r378191131
49+ destFileStream . destroy ( ) ;
50+ } ) ;
5351}
0 commit comments