get method

FutureOr<CacheEntry> get({
  1. String? url,
  2. String? checksum,
  3. dynamic onReceiveProgress(
    1. int count,
    2. int total
    )?,
  4. CancelToken? cancelToken,
  5. Future<void> onForbidden()?,
  6. CacheResponseType responseType = CacheResponseType.bytes,
})

Returns the bytes of File identified by its checksum.

At least one of url or checksum arguments must be provided.

Retries itself using exponential backoff algorithm on a failure, which can be canceled with a cancelToken.

Implementation

FutureOr<CacheEntry> get({
  String? url,
  String? checksum,
  Function(int count, int total)? onReceiveProgress,
  CancelToken? cancelToken,
  Future<void> Function()? onForbidden,
  CacheResponseType responseType = CacheResponseType.bytes,
}) {
  // Web does not support file caching.
  if (PlatformUtils.isWeb) {
    responseType = CacheResponseType.bytes;
  }

  // Try to retrieve the [CacheEntry] by URL as well, yet [checksum] is still
  // more preferred.
  final String? key = checksum ?? url;

  if (key != null && FIFOCache.exists(key)) {
    final Uint8List? bytes = FIFOCache.get(key);

    if (bytes != null) {
      switch (responseType) {
        case CacheResponseType.file:
          // If [CacheEntry] is supposed to contain a [File], and we don't
          // have a [checksum], then there won't be a [File], thus we should
          // break and proceed to fetch the [File] by the [url] provided.
          if (checksum == null) {
            break;
          }

          return Future(
            () async => CacheEntry(file: await add(bytes, checksum, url)),
          );

        case CacheResponseType.bytes:
          return CacheEntry(bytes: bytes);
      }
    }
  }

  return Future(() async {
    if (checksum != null) {
      final Directory? cache = await PlatformUtils.cacheDirectory;

      if (cache != null) {
        final File file = File('${cache.path}/$checksum');

        if (await file.exists()) {
          switch (responseType) {
            case CacheResponseType.file:
              return CacheEntry(file: file);

            case CacheResponseType.bytes:
              final Uint8List bytes = await file.readAsBytes();
              FIFOCache.set(checksum, bytes);
              return CacheEntry(bytes: bytes);
          }
        }
      }
    }

    if (url != null) {
      try {
        final Uint8List? data = await Backoff.run(() async {
          Response? data;

          try {
            data = await (await PlatformUtils.dio).get(
              url,
              options: Options(responseType: ResponseType.bytes),
              cancelToken: cancelToken,
              onReceiveProgress: onReceiveProgress,
            );
          } on DioException catch (e) {
            if (e.response?.statusCode == 403) {
              await onForbidden?.call();
              return null;
            }
          }

          if (data?.data != null && data!.statusCode == 200) {
            return data.data as Uint8List;
          } else {
            throw Exception('Data is not loaded');
          }
        }, cancelToken);

        switch (responseType) {
          case CacheResponseType.file:
            return Future(
              () async => CacheEntry(
                file: data == null ? null : await add(data, checksum, url),
              ),
            );

          case CacheResponseType.bytes:
            if (data != null) {
              add(data, checksum, url);
            }
            return CacheEntry(bytes: data);
        }
      } on OperationCanceledException catch (_) {
        return CacheEntry();
      }
    }

    return CacheEntry();
  });
}