瀏覽代碼

Refactor fileHash handling

Neeraj Gupta 2 年之前
父節點
當前提交
68738c5c56

+ 18 - 8
lib/db/files_db.dart

@@ -1,6 +1,5 @@
 import 'dart:io';
 import 'dart:io';
 
 
-import 'package:flutter/foundation.dart';
 import 'package:logging/logging.dart';
 import 'package:logging/logging.dart';
 import 'package:path/path.dart';
 import 'package:path/path.dart';
 import 'package:path_provider/path_provider.dart';
 import 'package:path_provider/path_provider.dart';
@@ -10,6 +9,7 @@ import 'package:photos/models/file_load_result.dart';
 import 'package:photos/models/file_type.dart';
 import 'package:photos/models/file_type.dart';
 import 'package:photos/models/location.dart';
 import 'package:photos/models/location.dart';
 import 'package:photos/models/magic_metadata.dart';
 import 'package:photos/models/magic_metadata.dart';
+import 'package:photos/utils/file_uploader_util.dart';
 import 'package:sqflite/sqflite.dart';
 import 'package:sqflite/sqflite.dart';
 import 'package:sqflite_migration/sqflite_migration.dart';
 import 'package:sqflite_migration/sqflite_migration.dart';
 
 
@@ -816,17 +816,27 @@ class FilesDB {
   }
   }
 
 
   Future<List<File>> getUploadedFilesWithHashes(
   Future<List<File>> getUploadedFilesWithHashes(
-    List<String> hash,
+    FileHashData hashData,
     FileType fileType,
     FileType fileType,
     int ownerID,
     int ownerID,
   ) async {
   ) async {
-    // look up two hash at max, for handling live photos
-    assert(hash.length < 3, "number of hash can not be more than 2");
+    String inParam = "'${hashData.fileHash}'";
+    if (fileType == FileType.livePhoto && hashData.zipHash != null) {
+      inParam += ",'${hashData.zipHash}'";
+    }
+
     final db = await instance.database;
     final db = await instance.database;
-    String rawQuery = 'SELECT * from files where ($columnUploadedFileID != '
-        'NULL OR $columnUploadedFileID != -1) AND $columnOwnerID = $ownerID '
-        'AND ($columnHash = "${hash.first}" OR $columnHash = "${hash.last}")';
-    final rows = await db.rawQuery(rawQuery, []);
+    final rows = await db.query(
+      table,
+      where: '($columnUploadedFileID != NULL OR $columnUploadedFileID != -1) '
+          'AND $columnOwnerID = ? AND $columnFileType ='
+          ' ? '
+          'AND $columnHash IN ($inParam)',
+      whereArgs: [
+        ownerID,
+        getInt(fileType),
+      ],
+    );
     if (rows.isNotEmpty) {
     if (rows.isNotEmpty) {
       return _convertToFiles(rows);
       return _convertToFiles(rows);
     } else {
     } else {

+ 4 - 8
lib/models/file.dart

@@ -53,7 +53,9 @@ class File extends EnteFile {
 
 
   set pubMagicMetadata(val) => _pubMmd = val;
   set pubMagicMetadata(val) => _pubMmd = val;
 
 
-  static const kCurrentMetadataVersion = 1;
+  // in Version 1, live photo hash is stored as zip's hash.
+  // in V2: LivePhoto hash is stored as imgHash:vidHash
+  static const kCurrentMetadataVersion = 2;
 
 
   File();
   File();
 
 
@@ -154,13 +156,7 @@ class File extends EnteFile {
         creationTime = exifTime.microsecondsSinceEpoch;
         creationTime = exifTime.microsecondsSinceEpoch;
       }
       }
     }
     }
-    // in metadataVersion V1, the hash for livePhoto is the hash of the
-    // zipped file.
-    // web uploads files without MetadataVersion and upload image hash as 'ha
-    // sh' key and video as 'vidHash'
-    hash = (fileType == FileType.livePhoto)
-        ? mediaUploadData.zipHash
-        : mediaUploadData.fileHash;
+    hash = mediaUploadData.hashData?.fileHash;
     return getMetadata();
     return getMetadata();
   }
   }
 
 

+ 4 - 3
lib/services/local_file_update_service.dart

@@ -106,9 +106,10 @@ class LocalFileUpdateService {
       MediaUploadData uploadData;
       MediaUploadData uploadData;
       try {
       try {
         uploadData = await getUploadDataFromEnteFile(file);
         uploadData = await getUploadDataFromEnteFile(file);
-        if (file.hash != null ||
-            (file.hash == uploadData.fileHash ||
-                file.hash == uploadData.zipHash)) {
+        if (uploadData.hashData != null &&
+            file.hash != null &&
+            (file.hash == uploadData.hashData.fileHash ||
+                file.hash == uploadData.hashData.zipHash)) {
           _logger.info("Skip file update as hash matched ${file.tag()}");
           _logger.info("Skip file update as hash matched ${file.tag()}");
         } else {
         } else {
           _logger.info(
           _logger.info(

+ 6 - 9
lib/utils/file_uploader.dart

@@ -447,10 +447,10 @@ class FileUploader {
   }
   }
 
 
   /*
   /*
-  // _mapToExistingUpload links the current file to be uploaded with the
-  // existing files. If the link is successful, it returns true other false.
-   When false, we should go ahead and re-upload or update the file
-    It performs following checks:
+  _mapToExistingUpload links the fileToUpload with the existing uploaded
+  files. if the link is successful, it returns true otherwise false.
+  When false, we should go ahead and re-upload or update the file.
+  It performs following checks:
     a) Uploaded file with same localID and destination collection. Delete the
     a) Uploaded file with same localID and destination collection. Delete the
      fileToUpload entry
      fileToUpload entry
     b) Uploaded file in destination collection but with missing localID.
     b) Uploaded file in destination collection but with missing localID.
@@ -476,13 +476,10 @@ class FileUploader {
       );
       );
       return false;
       return false;
     }
     }
-    List<String> hash = [mediaUploadData.fileHash];
-    if (fileToUpload.fileType == FileType.livePhoto) {
-      hash.add(mediaUploadData.zipHash);
-    }
+
     final List<File> existingUploadedFiles =
     final List<File> existingUploadedFiles =
         await FilesDB.instance.getUploadedFilesWithHashes(
         await FilesDB.instance.getUploadedFilesWithHashes(
-      hash,
+      mediaUploadData.hashData,
       fileToUpload.fileType,
       fileToUpload.fileType,
       Configuration.instance.getUserID(),
       Configuration.instance.getUserID(),
     );
     );

+ 18 - 13
lib/utils/file_uploader_util.dart

@@ -26,22 +26,27 @@ class MediaUploadData {
   final io.File sourceFile;
   final io.File sourceFile;
   final Uint8List thumbnail;
   final Uint8List thumbnail;
   final bool isDeleted;
   final bool isDeleted;
-  // presents the hash for the original video or image file.
-  // for livePhotos, fileHash represents the image hash value
-  final String fileHash;
-  final String liveVideoHash;
-  final String zipHash;
+  final FileHashData hashData;
 
 
   MediaUploadData(
   MediaUploadData(
     this.sourceFile,
     this.sourceFile,
     this.thumbnail,
     this.thumbnail,
     this.isDeleted, {
     this.isDeleted, {
-    this.fileHash,
-    this.liveVideoHash,
-    this.zipHash,
+    this.hashData,
   });
   });
 }
 }
 
 
+class FileHashData {
+  // For livePhotos, the fileHash value will be imageHash:videoHash
+  final String fileHash;
+
+  // zipHash is used to take care of existing live photo uploads from older
+  // mobile clients
+  String zipHash;
+
+  FileHashData(this.fileHash, {this.zipHash});
+}
+
 Future<MediaUploadData> getUploadDataFromEnteFile(ente.File file) async {
 Future<MediaUploadData> getUploadDataFromEnteFile(ente.File file) async {
   if (file.isSharedMediaToAppSandbox()) {
   if (file.isSharedMediaToAppSandbox()) {
     return await _getMediaUploadDataFromAppCache(file);
     return await _getMediaUploadDataFromAppCache(file);
@@ -54,7 +59,7 @@ Future<MediaUploadData> _getMediaUploadDataFromAssetFile(ente.File file) async {
   io.File sourceFile;
   io.File sourceFile;
   Uint8List thumbnailData;
   Uint8List thumbnailData;
   bool isDeleted;
   bool isDeleted;
-  String fileHash, livePhotoVideoHash, zipHash;
+  String fileHash, zipHash;
 
 
   // The timeouts are to safeguard against https://github.com/CaiJingLong/flutter_photo_manager/issues/467
   // The timeouts are to safeguard against https://github.com/CaiJingLong/flutter_photo_manager/issues/467
   final asset = await file
   final asset = await file
@@ -97,7 +102,9 @@ Future<MediaUploadData> _getMediaUploadDataFromAssetFile(ente.File file) async {
       _logger.severe(errMsg);
       _logger.severe(errMsg);
       throw InvalidFileUploadState(errMsg);
       throw InvalidFileUploadState(errMsg);
     }
     }
-    livePhotoVideoHash = Sodium.bin2base64(await CryptoUtil.getHash(videoUrl));
+    String livePhotoVideoHash =
+        Sodium.bin2base64(await CryptoUtil.getHash(videoUrl));
+    fileHash = '$fileHash:$livePhotoVideoHash';
     final tempPath = Configuration.instance.getTempDirectory();
     final tempPath = Configuration.instance.getTempDirectory();
     // .elp -> ente live photo
     // .elp -> ente live photo
     final livePhotoPath = tempPath + file.generatedID.toString() + ".elp";
     final livePhotoPath = tempPath + file.generatedID.toString() + ".elp";
@@ -138,9 +145,7 @@ Future<MediaUploadData> _getMediaUploadDataFromAssetFile(ente.File file) async {
     sourceFile,
     sourceFile,
     thumbnailData,
     thumbnailData,
     isDeleted,
     isDeleted,
-    fileHash: fileHash,
-    liveVideoHash: livePhotoVideoHash,
-    zipHash: zipHash,
+    hashData: FileHashData(fileHash, zipHash: zipHash),
   );
   );
 }
 }