downloadFile method

Future<DownloadResult> downloadFile({
  1. required String url,
  2. String? savePath,
  3. String? filename,
  4. Map<String, dynamic>? headers,
  5. dynamic onProgress(
    1. int received,
    2. int total
    )?,
  6. CancelToken? cancelToken,
})

Download file from URL

Implementation

Future<DownloadResult> downloadFile({
  required String url,
  String? savePath,
  String? filename,
  Map<String, dynamic>? headers,
  Function(int received, int total)? onProgress,
  CancelToken? cancelToken,
}) async {
  try {
    // Determine save path
    final filePath = await _determineFilePath(savePath, filename, url);

    // Create cancel token if not provided
    final token = cancelToken ?? CancelToken();

    // Store active download
    _activeDownloads[url] = token;

    // Log download start
    _logger.log('📥 Starting download: $url');
    _logger.log('💾 Save path: $filePath');

    final startTime = DateTime.now();

    // Download file
    await _dio.download(
      url,
      filePath,
      options: Options(
        headers: {
          ..._config.globalHeaders,
          if (headers != null) ...headers,
        },
        receiveTimeout: _config.receiveTimeout,
      ),
      cancelToken: token,
      onReceiveProgress: (received, total) {
        // Call progress callback
        onProgress?.call(received, total);

        // Log progress
        if (_config.enableLogs && total != -1) {
          _logger.logDownloadProgress(
            url: url,
            received: received,
            total: total,
          );
        }
      },
      deleteOnError: true,
    );

    // Remove from active downloads
    _activeDownloads.remove(url);

    final duration = DateTime.now().difference(startTime);
    final file = File(filePath);
    final fileSize = file.lengthSync();

    _logger.log(
      '✅ Download completed in ${duration.inMilliseconds}ms | Size: ${_formatBytes(fileSize)}',
    );

    return DownloadResult(
      success: true,
      filePath: filePath,
      fileSize: fileSize,
      duration: duration,
    );
  } on DioException catch (e) {
    _activeDownloads.remove(url);

    if (e.type == DioExceptionType.cancel) {
      _logger.log('Download cancelled: $url', isError: true);
      return DownloadResult(
        success: false,
        error: 'Download cancelled',
      );
    }

    _logger.log('Download failed: ${e.message}', isError: true);
    return DownloadResult(
      success: false,
      error: e.message ?? 'Download failed',
    );
  } catch (e) {
    _activeDownloads.remove(url);
    _logger.log('Download failed: $e', isError: true);
    return DownloadResult(
      success: false,
      error: e.toString(),
    );
  }
}