22// for details. All rights reserved. Use of this source code is governed by a
33// BSD-style license that can be found in the LICENSE file.
44
5+ import 'dart:async' ;
56import 'dart:io' ;
67
8+ import '../http.dart' show ByteStream;
79import 'base_client.dart' ;
810import 'base_request.dart' ;
911import 'exception.dart' ;
1012import 'io_streamed_response.dart' ;
13+ import 'utils.dart' ;
1114
1215/// Create an [IOClient] .
1316///
@@ -22,6 +25,7 @@ BaseClient createClient() => IOClient();
2225class _ClientSocketException extends ClientException
2326 implements SocketException {
2427 final SocketException cause;
28+
2529 _ClientSocketException (SocketException e, Uri url)
2630 : cause = e,
2731 super (e.message, url);
@@ -44,26 +48,50 @@ class IOClient extends BaseClient {
4448 IOClient ([HttpClient ? inner]) : _inner = inner ?? HttpClient ();
4549
4650 /// Sends an HTTP request and asynchronously returns the response.
51+ ///
52+ /// If [onUploadProgress] callback is provided and length is computable,
53+ /// [onUploadProgress] will execute for each chunk was sent.
54+ ///
55+ /// lengthComputable :
56+ /// library.html : xhr.lengthComputable
57+ /// library.io : content-length is provided (MultipartRequest provide)
4758 @override
48- Future <IOStreamedResponse > send (BaseRequest request) async {
59+ Future <IOStreamedResponse > send (BaseRequest request,
60+ {OnUploadProgress ? onUploadProgress}) async {
4961 if (_inner == null ) {
5062 throw ClientException (
5163 'HTTP request failed. Client is already closed.' , request.url);
5264 }
5365
5466 var stream = request.finalize ();
5567
68+ ByteStream ? handledStream;
69+
70+ var contentLength = request.contentLength;
71+ if (onUploadProgress != null && contentLength != null ) {
72+ var load = 0 ;
73+ handledStream =
74+ ByteStream (stream.transform (StreamTransformer .fromBind ((d) async * {
75+ await for (var data in d) {
76+ load += data.length;
77+ onUploadProgress (contentLength, load);
78+ yield data;
79+ }
80+ })));
81+ }
82+
5683 try {
5784 var ioRequest = (await _inner! .openUrl (request.method, request.url))
5885 ..followRedirects = request.followRedirects
5986 ..maxRedirects = request.maxRedirects
60- ..contentLength = (request. contentLength ?? - 1 )
87+ ..contentLength = (contentLength ?? - 1 )
6188 ..persistentConnection = request.persistentConnection;
6289 request.headers.forEach ((name, value) {
6390 ioRequest.headers.set (name, value);
6491 });
6592
66- var response = await stream.pipe (ioRequest) as HttpClientResponse ;
93+ var response =
94+ await (handledStream ?? stream).pipe (ioRequest) as HttpClientResponse ;
6795
6896 var headers = < String , String > {};
6997 response.headers.forEach ((key, values) {
0 commit comments