file_download_util.dart 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import 'dart:io' as io;
  2. import 'dart:typed_data';
  3. import 'package:dio/dio.dart';
  4. import 'package:flutter_sodium/flutter_sodium.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. Sodium.base642bin(file.fileDecryptionHeader!),
  56. decryptFileKey(file),
  57. );
  58. _logger.info("File decrypted: " + file.uploadedFileID.toString());
  59. await encryptedFile.delete();
  60. return decryptedFile;
  61. });
  62. }
  63. Uint8List decryptFileKey(ente.File file) {
  64. final encryptedKey = Sodium.base642bin(file.encryptedKey!);
  65. final nonce = Sodium.base642bin(file.keyDecryptionNonce!);
  66. final collectionKey =
  67. CollectionsService.instance.getCollectionKey(file.collectionID!);
  68. return CryptoUtil.decryptSync(encryptedKey, collectionKey, nonce);
  69. }