downloadFile method

Future<File> downloadFile(
  1. String url,
  2. String filePath, {
  3. int? expectedSize,
  4. String? resourceName,
})

Downloads a file from a URL to a specified path.

If the file already exists and matches the expected size, download is skipped. Progress is reported via the download progress callback if one is set.

url The URL to download the file from.

filePath The local path where the file should be saved.

expectedSize Optional expected file size for validation.

resourceName Optional display name for the resource being downloaded.

Returns the downloaded File object.

Implementation

Future<File> downloadFile(
  String url,
  String filePath, {
  int? expectedSize,
  String? resourceName,
}) async {
  final file = File(filePath);
  final displayName = resourceName ?? p.basename(filePath);

  if (await file.exists() && expectedSize != null) {
    final fileSize = await file.length();
    if (fileSize == expectedSize) {
      if (_onDownloadProgress != null) {
        _onDownloadProgress(displayName, expectedSize, expectedSize, 100.0);
      }
      return file;
    }
  }

  await ensureDirectory(p.dirname(filePath));

  try {
    final client = http.Client();
    final request = http.Request('GET', Uri.parse(url));
    final response = await client.send(request);

    if (response.statusCode == 200) {
      final contentLength = response.contentLength ?? -1;
      final sink = file.openWrite();
      int received = 0;
      int lastReportedPercentage = 0;

      await response.stream.listen((data) {
        sink.add(data);
        received += data.length;

        if (_onDownloadProgress != null && contentLength > 0) {
          final percentage = (received / contentLength) * 100;
          final reportPercentage =
              (percentage ~/ _progressReportRate) * _progressReportRate;

          if (reportPercentage > lastReportedPercentage) {
            lastReportedPercentage = reportPercentage;
            final clampedPercentage = max(0.0, min(percentage, 100.0));
            _onDownloadProgress(
              displayName,
              received,
              contentLength,
              clampedPercentage,
            );
          }
        }
      }).asFuture<void>();

      await sink.close();
      client.close();

      if (_onDownloadProgress != null && contentLength > 0) {
        _onDownloadProgress(displayName, contentLength, contentLength, 100.0);
      }

      return file;
    } else {
      client.close();
      throw Exception('Failed to download file: HTTP ${response.statusCode}');
    }
  } catch (e) {
    debugPrint('Error downloading file from $url: $e');
    rethrow;
  }
}