file_download_util.dart 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import 'dart:io' as io;
  2. import 'dart:typed_data';
  3. import "package:computer/computer.dart";
  4. import 'package:dio/dio.dart';
  5. import 'package:logging/logging.dart';
  6. import 'package:photos/core/configuration.dart';
  7. import 'package:photos/core/network/network.dart';
  8. import 'package:photos/models/file.dart' as ente;
  9. import 'package:photos/services/collections_service.dart';
  10. import 'package:photos/utils/crypto_util.dart';
  11. final _logger = Logger("file_download_util");
  12. Future<io.File?> downloadAndDecrypt(
  13. ente.File file, {
  14. ProgressCallback? progressCallback,
  15. }) {
  16. _logger.info("Downloading file " + file.uploadedFileID.toString());
  17. final encryptedFilePath = Configuration.instance.getTempDirectory() +
  18. file.generatedID.toString() +
  19. ".encrypted";
  20. final encryptedFile = io.File(encryptedFilePath);
  21. final startTime = DateTime.now().millisecondsSinceEpoch;
  22. return NetworkClient.instance
  23. .getDio()
  24. .download(
  25. file.downloadUrl,
  26. encryptedFilePath,
  27. options: Options(
  28. headers: {"X-Auth-Token": Configuration.instance.getToken()},
  29. ),
  30. onReceiveProgress: progressCallback,
  31. )
  32. .then((response) async {
  33. if (response.statusCode != 200) {
  34. _logger.warning("Could not download file: ", response.toString());
  35. return null;
  36. } else if (!encryptedFile.existsSync()) {
  37. _logger.warning("File was not downloaded correctly.");
  38. return null;
  39. }
  40. _logger.info("File downloaded: " + file.uploadedFileID.toString());
  41. _logger.info(
  42. "Download speed: " +
  43. (await io.File(encryptedFilePath).length() /
  44. (DateTime.now().millisecondsSinceEpoch - startTime))
  45. .toString() +
  46. "kBps",
  47. );
  48. final decryptedFilePath = Configuration.instance.getTempDirectory() +
  49. file.generatedID.toString() +
  50. ".decrypted";
  51. final decryptedFile = io.File(decryptedFilePath);
  52. await CryptoUtil.decryptFile(
  53. encryptedFilePath,
  54. decryptedFilePath,
  55. CryptoUtil.base642bin(file.fileDecryptionHeader!),
  56. getFileKey(file),
  57. );
  58. _logger.info("File decrypted: " + file.uploadedFileID.toString());
  59. await encryptedFile.delete();
  60. return decryptedFile;
  61. });
  62. }
  63. Uint8List getFileKey(ente.File file) {
  64. final encryptedKey = CryptoUtil.base642bin(file.encryptedKey!);
  65. final nonce = CryptoUtil.base642bin(file.keyDecryptionNonce!);
  66. final collectionKey =
  67. CollectionsService.instance.getCollectionKey(file.collectionID!);
  68. return CryptoUtil.decryptSync(encryptedKey, collectionKey, nonce);
  69. }
  70. Future<Uint8List> getFileKeyUsingBgWorker(ente.File file) async {
  71. final collectionKey =
  72. CollectionsService.instance.getCollectionKey(file.collectionID!);
  73. return await Computer.shared().compute(
  74. _decryptFileKey,
  75. param: <String, dynamic>{
  76. "encryptedKey": file.encryptedKey,
  77. "keyDecryptionNonce": file.keyDecryptionNonce,
  78. "collectionKey": collectionKey,
  79. },
  80. );
  81. }
  82. Uint8List _decryptFileKey(Map<String, dynamic> args) {
  83. final encryptedKey = CryptoUtil.base642bin(args["encryptedKey"]);
  84. final nonce = CryptoUtil.base642bin(args["keyDecryptionNonce"]);
  85. return CryptoUtil.decryptSync(
  86. encryptedKey,
  87. args["collectionKey"],
  88. nonce,
  89. );
  90. }