download method

Future<(List<int>?, ClientException?)> download({
  1. required String url,
  2. Map<String, String>? headers,
  3. Duration? timeout,
  4. ClientType? clientType,
  5. OnProgress? onProgress,
  6. String? cancelKey,
  7. void onSuccess(
    1. List<int> bytes
    )?,
  8. OnError? onError,
})

Downloads a file from the specified URL.

Returns a tuple of (bytes, error). Optionally accepts callbacks for convenient response handling.

Implementation

Future<(List<int>?, ClientException?)> download({
  required String url,
  Map<String, String>? headers,
  Duration? timeout,
  ClientType? clientType,
  OnProgress? onProgress,
  String? cancelKey,
  // Optional callbacks
  void Function(List<int> bytes)? onSuccess,
  OnError? onError,
}) async {
  final fullUrl = _buildUrl(url);
  final useClient = clientType ?? config.clientType;

  try {
    if (useClient == ClientType.dio) {
      dio.CancelToken? cancelToken;
      if (cancelKey != null) {
        cancelToken = dio.CancelToken();
        _cancelTokens[cancelKey] = cancelToken;
      }

      final response = await _dio.get<List<int>>(
        fullUrl,
        options: dio.Options(
          headers: headers,
          responseType: dio.ResponseType.bytes,
          receiveTimeout: timeout ?? config.receiveTimeout,
        ),
        onReceiveProgress: onProgress,
        cancelToken: cancelToken,
      );

      if (cancelKey != null) _cancelTokens.remove(cancelKey);

      if (response.statusCode != null &&
          response.statusCode! >= 200 &&
          response.statusCode! < 300) {
        final result = (response.data, null);
        if (result.$1 != null) {
          onSuccess?.call(result.$1!);
        }
        return result;
      } else {
        final result = (
          null,
          ClientException(
            message: 'Download failed with status ${response.statusCode}',
            url: fullUrl,
            statusCode: response.statusCode,
            type: ClientErrorType.badResponse,
          )
        );
        onError?.call(result.$2);
        return result;
      }
    } else {
      final response = await _http
          .get(Uri.parse(fullUrl), headers: headers)
          .timeout(timeout ?? config.receiveTimeout);

      if (response.statusCode >= 200 && response.statusCode < 300) {
        final result = (response.bodyBytes, null);
        onSuccess?.call(result.$1);
        return result;
      } else {
        final result = (
          null,
          ClientException(
            message: 'Download failed with status ${response.statusCode}',
            url: fullUrl,
            statusCode: response.statusCode,
            type: ClientErrorType.badResponse,
          )
        );
        onError?.call(result.$2);
        return result;
      }
    }
  } catch (e) {
    if (cancelKey != null) _cancelTokens.remove(cancelKey);
    final result = (null, _toException(e, fullUrl));
    onError?.call(result.$2);
    return result;
  }
}