backup.service.dart 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import 'dart:async';
  2. import 'dart:convert';
  3. import 'dart:io';
  4. import 'package:dio/dio.dart';
  5. import 'package:flutter/material.dart';
  6. import 'package:hive/hive.dart';
  7. import 'package:immich_mobile/constants/hive_box.dart';
  8. import 'package:immich_mobile/shared/services/network.service.dart';
  9. import 'package:immich_mobile/shared/models/device_info.model.dart';
  10. import 'package:immich_mobile/utils/dio_http_interceptor.dart';
  11. import 'package:immich_mobile/utils/files_helper.dart';
  12. import 'package:photo_manager/photo_manager.dart';
  13. import 'package:http_parser/http_parser.dart';
  14. import 'package:path/path.dart' as p;
  15. class BackupService {
  16. final NetworkService _networkService = NetworkService();
  17. Future<List<String>> getDeviceBackupAsset() async {
  18. String deviceId = Hive.box(userInfoBox).get(deviceIdKey);
  19. Response response = await _networkService.getRequest(url: "asset/$deviceId");
  20. List<dynamic> result = jsonDecode(response.toString());
  21. return result.cast<String>();
  22. }
  23. backupAsset(List<AssetEntity> assetList, CancelToken cancelToken, Function(String, String) singleAssetDoneCb,
  24. Function(int, int) uploadProgress) async {
  25. var dio = Dio();
  26. dio.interceptors.add(AuthenticatedRequestInterceptor());
  27. String deviceId = Hive.box(userInfoBox).get(deviceIdKey);
  28. String savedEndpoint = Hive.box(userInfoBox).get(serverEndpointKey);
  29. File? file;
  30. MultipartFile assetRawUploadData;
  31. MultipartFile thumbnailUploadData;
  32. for (var entity in assetList) {
  33. try {
  34. if (entity.type == AssetType.video) {
  35. file = await entity.originFile;
  36. } else {
  37. file = await entity.originFile.timeout(const Duration(seconds: 5));
  38. }
  39. if (file != null) {
  40. FormData formData;
  41. String originalFileName = await entity.titleAsync;
  42. String fileNameWithoutPath = originalFileName.toString().split(".")[0];
  43. var fileExtension = p.extension(file.path);
  44. var mimeType = FileHelper.getMimeType(file.path);
  45. assetRawUploadData = await MultipartFile.fromFile(
  46. file.path,
  47. filename: fileNameWithoutPath,
  48. contentType: MediaType(
  49. mimeType["type"],
  50. mimeType["subType"],
  51. ),
  52. );
  53. formData = FormData.fromMap({
  54. 'deviceAssetId': entity.id,
  55. 'deviceId': deviceId,
  56. 'assetType': _getAssetType(entity.type),
  57. 'createdAt': entity.createDateTime.toIso8601String(),
  58. 'modifiedAt': entity.modifiedDateTime.toIso8601String(),
  59. 'isFavorite': entity.isFavorite,
  60. 'fileExtension': fileExtension,
  61. 'duration': entity.videoDuration,
  62. 'assetData': [assetRawUploadData]
  63. });
  64. // Build thumbnail multipart data
  65. var thumbnailData = await entity.thumbDataWithSize(1280, 720);
  66. if (thumbnailData != null) {
  67. thumbnailUploadData = MultipartFile.fromBytes(
  68. List.from(thumbnailData),
  69. filename: fileNameWithoutPath,
  70. contentType: MediaType(
  71. "image",
  72. "jpeg",
  73. ),
  74. );
  75. // Send thumbnail data if it is exist
  76. formData = FormData.fromMap({
  77. 'deviceAssetId': entity.id,
  78. 'deviceId': deviceId,
  79. 'assetType': _getAssetType(entity.type),
  80. 'createdAt': entity.createDateTime.toIso8601String(),
  81. 'modifiedAt': entity.modifiedDateTime.toIso8601String(),
  82. 'isFavorite': entity.isFavorite,
  83. 'fileExtension': fileExtension,
  84. 'duration': entity.videoDuration,
  85. 'thumbnailData': [thumbnailUploadData],
  86. 'assetData': [assetRawUploadData]
  87. });
  88. }
  89. Response res = await dio.post(
  90. '$savedEndpoint/asset/upload',
  91. data: formData,
  92. cancelToken: cancelToken,
  93. onSendProgress: (sent, total) => uploadProgress(sent, total),
  94. );
  95. if (res.statusCode == 201) {
  96. singleAssetDoneCb(entity.id, deviceId);
  97. }
  98. }
  99. } on DioError catch (e) {
  100. debugPrint("DioError backupAsset: ${e.response}");
  101. break;
  102. } catch (e) {
  103. debugPrint("ERROR backupAsset: ${e.toString()}");
  104. continue;
  105. } finally {
  106. if (Platform.isIOS) {
  107. file?.deleteSync();
  108. }
  109. }
  110. }
  111. }
  112. String _getAssetType(AssetType assetType) {
  113. switch (assetType) {
  114. case AssetType.audio:
  115. return "AUDIO";
  116. case AssetType.image:
  117. return "IMAGE";
  118. case AssetType.video:
  119. return "VIDEO";
  120. case AssetType.other:
  121. return "OTHER";
  122. }
  123. }
  124. Future<DeviceInfoRemote> setAutoBackup(bool status, String deviceId, String deviceType) async {
  125. var res = await _networkService.patchRequest(url: 'device-info', data: {
  126. "isAutoBackup": status,
  127. "deviceId": deviceId,
  128. "deviceType": deviceType,
  129. });
  130. return DeviceInfoRemote.fromJson(res.toString());
  131. }
  132. }