import got from "got" ; import { PassThrough , pipeline as pipeline_callback } from "stream" ; import { promisify } from "util" ; import { BriefcaseStatus } from "@itwin/core-bentley" ; import { ProgressCallback , ResponseError } from "./Request" ; import { CancelRequest , DownloadFailed , UserCancelledError } from "../itwin-client/FileHandler" ; import { BufferedStream } from "./AzureFileHandler" ; import WriteStreamAtomic from "fs-write-stream-atomic" ; const pipeline = promisify ( pipeline_callback ) ; internal export async function downloadFileAtomic ( downloadUrl , downloadToPathname , fileSize ? , progressCallback ? , cancelRequest ? , bufferThreshold ? ) { let retryCount = 0 ; let closePromise ; while ( retryCount > - 1 ) { const fileStream = new WriteStreamAtomic ( downloadToPathname , { encoding : "binary" } ) ; closePromise = new Promise ( ( resolve ) => fileStream . once ( "close" , resolve ) ) ; const bufferedStream = ( bufferThreshold !== undefined ) ? new BufferedStream ( bufferThreshold ) : new PassThrough ( ) ; const downloadStream = got . stream ( downloadUrl ) ; downloadStream . retryCount = retryCount ; downloadStream . once ( "retry" , ( count ) => retryCount = count ) ; retryCount = - 1 ; if ( progressCallback ) { downloadStream . on ( "downloadProgress" , ( { transferred } ) => { progressCallback ( { loaded : transferred , total : fileSize , percent : fileSize ? 100 * transferred / fileSize : 0 } ) ; } ) ; } if ( cancelRequest !== undefined ) { cancelRequest . cancel = ( ) => { downloadStream . destroy ( new got . CancelError ( ) ) ; return true ; } ; } try { await pipeline ( downloadStream , bufferedStream , fileStream ) ; } catch ( error ) { if ( error instanceof got . CancelError ) throw new UserCancelledError ( BriefcaseStatus . DownloadCancelled , "User cancelled download" ) ; if ( error instanceof got . HTTPError ) throw new DownloadFailed ( error . response . statusCode , error . response . statusMessage ?? "Download failed" ) ; if ( error . code !== "ERR_STREAM_PREMATURE_CLOSE" ) throw ResponseError . parse ( error ) ; } finally { if ( cancelRequest !== undefined ) cancelRequest . cancel = ( ) => false ; await closePromise ! ; } } }