diff --git a/core/lib/data/network/download/download_client.dart b/core/lib/data/network/download/download_client.dart index 0d3985372..0f2d748e9 100644 --- a/core/lib/data/network/download/download_client.dart +++ b/core/lib/data/network/download/download_client.dart @@ -1,15 +1,22 @@ import 'dart:convert'; import 'dart:io'; +import 'dart:typed_data'; -import 'package:core/core.dart'; +import 'package:core/data/network/dio_client.dart'; +import 'package:core/data/utils/compress_file_utils.dart'; +import 'package:core/presentation/extensions/html_extension.dart'; +import 'package:core/utils/app_logger.dart'; +import 'package:core/utils/build_utils.dart'; import 'package:dio/dio.dart'; +import 'package:flutter/foundation.dart'; class DownloadClient { final DioClient _dioClient; + final CompressFileUtils _compressFileUtils; - DownloadClient(this._dioClient); + DownloadClient(this._dioClient, this._compressFileUtils); Future downloadFile( String url, @@ -28,14 +35,84 @@ class DownloadClient { return (responseBody as ResponseBody); } - Future downloadImageAsBase64(String url) async { + Future downloadImageAsBase64( + String url, + String cid, + String fileExtension, + String fileName, + { + Uint8List? bytesData, + double? maxWidth, + bool? compress, + } + ) async { try { - final response = await _dioClient.get( - url, - options: Options(responseType: ResponseType.bytes)); - return base64Encode(response); + if (bytesData == null) { + log('DownloadClient::downloadImageAsBase64(): bytesData is NULL'); + bytesData = await _dioClient.get(url, options: Options(responseType: ResponseType.bytes)); + } + + if (bytesData == null) { + return null; + } + + if (BuildUtils.isWeb) { + final base64Uri = encodeToBase64Uri({ + 'bytesData': bytesData, + 'mimeType': 'image/$fileExtension', + 'cid': cid, + 'fileName': fileName + }); + + return base64Uri; + } else { + if (compress == true) { + final bytesDataCompressed = await _compressFileUtils.compressBytesDataImage( + bytesData, + maxWidth: maxWidth?.toInt()); + + final base64Uri = await compute(encodeToBase64Uri, { + 'bytesData': bytesDataCompressed, + 'mimeType': 'image/$fileExtension', + 'cid': cid, + 'fileName': fileName + }); + + return base64Uri; + } else { + final base64Uri = await compute(encodeToBase64Uri, { + 'bytesData': bytesData, + 'mimeType': 'image/$fileExtension', + 'cid': cid, + 'fileName': fileName + }); + + return base64Uri; + } + } } catch (e) { - return url; + log('DownloadClient::downloadImageAsBase64(): ERROR: $e'); + return null; } } + + static String encodeToBase64Uri(Map entryParam) { + var bytesData = entryParam['bytesData']; + var mimeType = entryParam['mimeType']; + final cid = entryParam['cid']; + var fileName = entryParam['fileName']; + + final base64Data = base64Encode(bytesData); + if (mimeType.endsWith('svg')) { + mimeType = 'image/svg+xml'; + } + if (!base64Data.endsWith('==')) { + base64Data.append('=='); + } + if (fileName.contains('.')) { + fileName = fileName.split('.').first; + } + final base64Uri = '$fileName'; + return base64Uri; + } } \ No newline at end of file diff --git a/core/lib/presentation/utils/html_transformer/dom/image_transformers.dart b/core/lib/presentation/utils/html_transformer/dom/image_transformers.dart index 8061ff118..eaba1445e 100644 --- a/core/lib/presentation/utils/html_transformer/dom/image_transformers.dart +++ b/core/lib/presentation/utils/html_transformer/dom/image_transformers.dart @@ -4,6 +4,7 @@ import 'dart:convert'; import 'package:core/core.dart'; import 'package:core/presentation/utils/html_transformer/base/dom_transformer.dart'; import 'package:dio/dio.dart'; +import 'package:flutter/foundation.dart'; import 'package:html/dom.dart'; class ImageTransformer extends DomTransformer { @@ -19,6 +20,7 @@ class ImageTransformer extends DomTransformer { DioClient? dioClient } ) async { + final compressFileUtils = CompressFileUtils(); final imageElements = document.getElementsByTagName('img'); await Future.wait(imageElements.map((imageElement) async { @@ -32,24 +34,50 @@ class ImageTransformer extends DomTransformer { final cid = src.replaceFirst('cid:', '').trim(); final cidUrlDownload = mapUrlDownloadCID[cid]; if (cidUrlDownload != null && cidUrlDownload.isNotEmpty && dioClient != null) { - final imgBase64 = await loadAsyncNetworkImageToBase64(dioClient, cidUrlDownload); - if (imgBase64 != null && imgBase64.isNotEmpty) { - imageElement.attributes['src'] = 'data:image/jpeg;base64,$imgBase64'; + final imgBase64Uri = await loadAsyncNetworkImageToBase64( + dioClient, + compressFileUtils, + cidUrlDownload); + if (imgBase64Uri.isNotEmpty) { + imageElement.attributes['src'] = imgBase64Uri; } } } })); } - - Future loadAsyncNetworkImageToBase64(DioClient dioClient, String imageUrl) async { + Future loadAsyncNetworkImageToBase64( + DioClient dioClient, + CompressFileUtils compressFileUtils, + String imageUrl + ) async { try { - final response = await dioClient.get( - imageUrl, - options: Options(responseType: ResponseType.bytes)); - return base64Encode(response); + var responseData = await dioClient.get( + imageUrl, + options: Options(responseType: ResponseType.bytes)); + + if (responseData != null) { + if (BuildUtils.isWeb) { + return encodeToBase64Uri(responseData); + } else { + final bytesCompressed = await compressFileUtils.compressBytesDataImage(responseData); + final base64Uri = await compute(encodeToBase64Uri, bytesCompressed); + return base64Uri; + } + } else { + return ''; + } } catch (e) { - return imageUrl; + return ''; } } + + static String encodeToBase64Uri(dynamic bytesData) { + final base64Data = base64Encode(bytesData); + if (!base64Data.endsWith('==')) { + base64Data.append('=='); + } + final base64Uri = 'data:image/jpeg;base64,$base64Data'; + return base64Uri; + } } \ No newline at end of file