@@ -54,26 +54,72 @@ public static async Task SaveAsAsync(this HttpResponseMessage httpResponse, stri
5454 await httpResponse . SaveAsAsync ( fileStream , cancellationToken ) . ConfigureAwait ( false ) ;
5555 }
5656
57+ /// <summary>
58+ /// 保存到目标流
59+ /// </summary>
60+ /// <param name="httpResponse"></param>
61+ /// <param name="destination">目标流</param>
62+ /// <param name="cancellationToken">取消令牌</param>
63+ /// <exception cref="ArgumentNullException"></exception>
64+ /// <exception cref="ArgumentException"></exception>
65+ /// <exception cref="OperationCanceledException"></exception>
66+ /// <returns></returns>
67+ public static async Task SaveAsAsync ( this HttpResponseMessage httpResponse , Stream destination , CancellationToken cancellationToken = default )
68+ {
69+ if ( destination == null )
70+ {
71+ throw new ArgumentNullException ( nameof ( destination ) ) ;
72+ }
73+
74+ var source = await httpResponse . Content . ReadAsStreamAsync ( ) . ConfigureAwait ( false ) ;
75+ await source . CopyToAsync ( destination , cancellationToken ) . ConfigureAwait ( false ) ;
76+ }
5777
5878 /// <summary>
5979 /// 保存到目标流
6080 /// </summary>
6181 /// <param name="httpResponse"></param>
62- /// <param name="stream">流</param>
82+ /// <param name="destination">目标流</param>
83+ /// <param name="progressChanged">进度变化</param>
6384 /// <param name="cancellationToken">取消令牌</param>
6485 /// <exception cref="ArgumentNullException"></exception>
6586 /// <exception cref="ArgumentException"></exception>
6687 /// <exception cref="OperationCanceledException"></exception>
6788 /// <returns></returns>
68- public static async Task SaveAsAsync ( this HttpResponseMessage httpResponse , Stream stream , CancellationToken cancellationToken = default )
89+ public static async Task SaveAsAsync ( this HttpResponseMessage httpResponse , Stream destination , Action < HttpProgress > progressChanged , CancellationToken cancellationToken = default )
6990 {
70- if ( stream == null )
91+ if ( destination == null )
7192 {
72- throw new ArgumentNullException ( nameof ( stream ) ) ;
93+ throw new ArgumentNullException ( nameof ( destination ) ) ;
7394 }
7495
96+ var recvSize = 0L ;
97+ var isCompleted = false ;
98+ var fileSize = httpResponse . Content . Headers . ContentLength ;
99+
100+ var buffer = new byte [ 8 * 1024 ] ;
75101 var source = await httpResponse . Content . ReadAsStreamAsync ( ) . ConfigureAwait ( false ) ;
76- await source . CopyToAsync ( stream , cancellationToken ) . ConfigureAwait ( false ) ;
102+
103+ while ( isCompleted == false && cancellationToken . IsCancellationRequested == false )
104+ {
105+ var length = await source . ReadAsync ( buffer , 0 , buffer . Length , cancellationToken ) . ConfigureAwait ( false ) ;
106+ if ( length == 0 )
107+ {
108+ if ( fileSize == null )
109+ {
110+ fileSize = recvSize ;
111+ }
112+ isCompleted = true ;
113+ }
114+ else
115+ {
116+ recvSize += length ;
117+ await destination . WriteAsync ( buffer , 0 , length , cancellationToken ) . ConfigureAwait ( false ) ;
118+ await destination . FlushAsync ( cancellationToken ) ;
119+ }
120+
121+ progressChanged . Invoke ( new HttpProgress ( fileSize , recvSize , isCompleted ) ) ;
122+ }
77123 }
78124 }
79125}
0 commit comments