@@ -33,12 +33,19 @@ internal partial class DownloadCommand : BaseCommand<TransferUtilityDownloadResp
3333 public override async Task < TransferUtilityDownloadResponse > ExecuteAsync ( CancellationToken cancellationToken )
3434 {
3535 ValidateRequest ( ) ;
36+
37+ FireTransferInitiatedEvent ( ) ;
38+
3639 GetObjectRequest getRequest = ConvertToGetObjectRequest ( this . _request ) ;
3740
3841 var maxRetries = _s3Client . Config . MaxErrorRetry ;
3942 var retries = 0 ;
4043 bool shouldRetry = false ;
4144 string mostRecentETag = null ;
45+ TransferUtilityDownloadResponse lastSuccessfulMappedResponse = null ;
46+ long ? totalBytesFromResponse = null ; // Track total bytes once we have response headers
47+ long totalTransferredBytes = 0 ;
48+
4249 do
4350 {
4451 shouldRetry = false ;
@@ -54,12 +61,16 @@ public override async Task<TransferUtilityDownloadResponse> ExecuteAsync(Cancell
5461 using ( var response = await this . _s3Client . GetObjectAsync ( getRequest , cancellationToken )
5562 . ConfigureAwait ( continueOnCapturedContext : false ) )
5663 {
64+ // Capture total bytes from response headers as soon as we get them
65+ totalBytesFromResponse = response . ContentLength ;
66+
5767 if ( ! string . IsNullOrEmpty ( mostRecentETag ) && ! string . Equals ( mostRecentETag , response . ETag ) )
5868 {
5969 //if the eTag changed, we need to retry from the start of the file
6070 mostRecentETag = response . ETag ;
6171 getRequest . ByteRange = null ;
6272 retries = 0 ;
73+ Interlocked . Exchange ( ref _totalTransferredBytes , 0 ) ;
6374 shouldRetry = true ;
6475 WaitBeforeRetry ( retries ) ;
6576 continue ;
@@ -101,6 +112,9 @@ await response.WriteResponseStreamToFileAsync(this._request.FilePath, false, can
101112 await response . WriteResponseStreamToFileAsync ( this . _request . FilePath , true , cancellationToken )
102113 . ConfigureAwait ( continueOnCapturedContext : false ) ;
103114 }
115+
116+ lastSuccessfulMappedResponse = ResponseMapper . MapGetObjectResponse ( response ) ;
117+ totalTransferredBytes = Interlocked . Read ( ref _totalTransferredBytes ) ;
104118 }
105119 }
106120 catch ( Exception exception )
@@ -109,6 +123,9 @@ await response.WriteResponseStreamToFileAsync(this._request.FilePath, true, canc
109123 shouldRetry = HandleExceptionForHttpClient ( exception , retries , maxRetries ) ;
110124 if ( ! shouldRetry )
111125 {
126+ // Pass total bytes if we have them from response headers, otherwise -1 for unknown
127+ FireTransferFailedEvent ( this . _request . FilePath , Interlocked . Read ( ref _totalTransferredBytes ) , totalBytesFromResponse ?? - 1 ) ;
128+
112129 if ( exception is IOException )
113130 {
114131 throw ;
@@ -131,8 +148,9 @@ await response.WriteResponseStreamToFileAsync(this._request.FilePath, true, canc
131148 WaitBeforeRetry ( retries ) ;
132149 } while ( shouldRetry ) ;
133150
134- // TODO map and return response
135- return new TransferUtilityDownloadResponse ( ) ;
151+ FireTransferCompletedEvent ( lastSuccessfulMappedResponse , this . _request . FilePath , totalTransferredBytes , totalBytesFromResponse ?? - 1 ) ;
152+
153+ return lastSuccessfulMappedResponse ;
136154 }
137155
138156 private static bool HandleExceptionForHttpClient ( Exception exception , int retries , int maxRetries )
0 commit comments