diff --git a/dio/lib/src/options.dart b/dio/lib/src/options.dart index c836798b0..2900972a4 100644 --- a/dio/lib/src/options.dart +++ b/dio/lib/src/options.dart @@ -41,6 +41,13 @@ enum ResponseType { /// Get the original bytes, the [Response.data] will be [List]. bytes, + + /// Get blob url. + /// This value is needed when you need content in the form of a blob url. + /// Only work in web. + /// + /// the [Response.data] will be [String]. + blobUrl, } /// {@template dio.options.ListFormat} diff --git a/plugins/web_adapter/lib/src/html/adapter.dart b/plugins/web_adapter/lib/src/html/adapter.dart index 5dc1cc881..d054c8ec3 100644 --- a/plugins/web_adapter/lib/src/html/adapter.dart +++ b/plugins/web_adapter/lib/src/html/adapter.dart @@ -38,7 +38,8 @@ class BrowserHttpClientAdapter implements HttpClientAdapter { xhrs.add(xhr); xhr ..open(options.method, '${options.uri}') - ..responseType = 'arraybuffer'; + ..responseType = + options.responseType == ResponseType.blobUrl ? 'blob' : 'arraybuffer'; final withCredentialsOption = options.extra['withCredentials']; if (withCredentialsOption != null) { @@ -65,18 +66,35 @@ class BrowserHttpClientAdapter implements HttpClientAdapter { final completer = Completer(); xhr.onLoad.first.then((_) { - final Uint8List body = (xhr.response as ByteBuffer).asUint8List(); - completer.complete( - ResponseBody.fromBytes( - body, - xhr.status!, - headers: xhr.responseHeaders.map((k, v) => MapEntry(k, v.split(','))), - statusMessage: xhr.statusText, - isRedirect: xhr.status == 302 || - xhr.status == 301 || - options.uri.toString() != xhr.responseUrl, - ), - ); + if (options.responseType == ResponseType.blobUrl) { + completer.complete( + ResponseBody.fromString( + Url.createObjectUrl(xhr.response), + xhr.status!, + headers: + xhr.responseHeaders.map((k, v) => MapEntry(k, v.split(','))), + statusMessage: xhr.statusText, + isRedirect: xhr.status == 302 || + xhr.status == 301 || + options.uri.toString() != xhr.responseUrl, + ), + ); + } else { + final Uint8List body = (xhr.response as ByteBuffer).asUint8List(); + completer.complete( + ResponseBody.fromBytes( + body, + xhr.status!, + headers: xhr.responseHeaders.map( + (k, v) => MapEntry(k, v.split(',')), + ), + statusMessage: xhr.statusText, + isRedirect: xhr.status == 302 || + xhr.status == 301 || + options.uri.toString() != xhr.responseUrl, + ), + ); + } }); Timer? connectTimeoutTimer; diff --git a/plugins/web_adapter/lib/src/html/dio_impl.dart b/plugins/web_adapter/lib/src/html/dio_impl.dart index f5adc61bd..ed4152263 100644 --- a/plugins/web_adapter/lib/src/html/dio_impl.dart +++ b/plugins/web_adapter/lib/src/html/dio_impl.dart @@ -1,5 +1,7 @@ // export '../js_interop/dio_impl.dart'; +import 'dart:async'; + import 'package:dio/dio.dart'; import 'adapter.dart'; @@ -27,9 +29,24 @@ class DioForBrowser with DioMixin implements Dio { String lengthHeader = Headers.contentLengthHeader, Object? data, Options? options, - }) { - throw UnsupportedError( - 'The download method is not available in the Web environment.', + }) async { + final Response response = await fetch( + RequestOptions( + baseUrl: urlPath, + data: data, + method: 'GET', + responseType: ResponseType.blobUrl, + queryParameters: queryParameters, + cancelToken: cancelToken, + onReceiveProgress: onReceiveProgress, + ), ); + + final completer = Completer(); + + // Set response in Completer + completer.complete(response); + + return completer.future; } }