Преглед на файлове

Add file extension guessing from ref and data

onevcat преди 1 година
родител
ревизия
c7c1e3d2e7
променени са 2 файла, в които са добавени 43 реда и са изтрити 0 реда
  1. 39 0
      Sources/General/ImageSource/LivePhotoSource.swift
  2. 4 0
      Sources/General/KingfisherManager+LivePhoto.swift

+ 39 - 0
Sources/General/ImageSource/LivePhotoSource.swift

@@ -51,6 +51,45 @@ public struct LivePhotoResource: Sendable {
     }
 }
 
+extension LivePhotoResource.FileType {
+    func determinedFileExtension(_ data: Data) -> String? {
+        switch self {
+        case .mov: return "mov"
+        case .heic: return "heic"
+        case .other(let ext):
+            if !ext.isEmpty {
+                return ext
+            }
+            return Self.guessedFileExtension(from: data)
+        }
+    }
+    
+    static let fytpChunk: [UInt8] = [0x66, 0x74, 0x79, 0x70]
+    static let heicChunk: [UInt8] = [0x68, 0x65, 0x69, 0x63]
+    static let qtChunk: [UInt8] = [0x71, 0x74, 0x20, 0x20] // quicktime
+    
+    static func guessedFileExtension(from data: Data) -> String? {
+        
+        guard data.count > 12 else { return nil }
+        
+        var buffer = [UInt8](repeating: 0, count: 12)
+        data.copyBytes(to: &buffer, count: 12)
+        
+        guard Array(buffer[4..<8]) == fytpChunk else {
+            return nil
+        }
+        
+        let fileTypeChunk = Array(buffer[8..<12])
+        if fileTypeChunk == heicChunk {
+            return "heic"
+        }
+        if fileTypeChunk == qtChunk {
+            return "mov"
+        }
+        return nil
+    }
+}
+
 extension Resource {
     var guessedFileType: LivePhotoResource.FileType {
         let pathExtension = downloadURL.pathExtension.lowercased()

+ 4 - 0
Sources/General/KingfisherManager+LivePhoto.swift

@@ -145,10 +145,13 @@ extension KingfisherManager {
                         with: resource.downloadURL,
                         options: options
                     )
+                    let fileExtension = resource.referenceFileType
+                        .determinedFileExtension(downloadedResource.originalData)
                     try await cache.storeToDisk(
                         downloadedResource.originalData,
                         forKey: resource.cacheKey,
                         processorIdentifier: options.processor.identifier,
+                        forcedExtension: fileExtension,
                         expiration: options.diskCacheExpiration
                     )
                     return downloadedResource
@@ -163,3 +166,4 @@ extension KingfisherManager {
         }
     }
 }
+