Bläddra i källkod

Merge pull request #1365 from onevcat/fix/disk-cache-throwing

Throw errors when creating cache file failure
Wei Wang 6 år sedan
förälder
incheckning
d9460a5c79
2 ändrade filer med 55 tillägg och 6 borttagningar
  1. 29 6
      Sources/Cache/DiskStorage.swift
  2. 26 0
      Sources/General/KingfisherError.swift

+ 29 - 6
Sources/Cache/DiskStorage.swift

@@ -108,6 +108,13 @@ public enum DiskStorage {
             }
 
             let fileURL = cacheFileURL(forKey: key)
+            do {
+                try data.write(to: fileURL)
+            } catch {
+                throw KingfisherError.cacheError(
+                    reason: .cannotCreateCacheFile(fileURL: fileURL, key: key, data: data, error: error)
+                )
+            }
 
             let now = Date()
             let attributes: [FileAttributeKey : Any] = [
@@ -116,7 +123,18 @@ public enum DiskStorage {
                 // The estimated expiration date.
                 .modificationDate: expiration.estimatedExpirationSinceNow.fileAttributeDate
             ]
-            config.fileManager.createFile(atPath: fileURL.path, contents: data, attributes: attributes)
+            do {
+                try config.fileManager.setAttributes(attributes, ofItemAtPath: fileURL.path)
+            } catch {
+                try? config.fileManager.removeItem(at: fileURL)
+                throw KingfisherError.cacheError(
+                    reason: .cannotSetCacheFileAttribute(
+                        filePath: fileURL.path,
+                        attributes: attributes,
+                        error: error
+                    )
+                )
+            }
         }
 
         func value(forKey key: String, extendingExpiration: ExpirationExtending = .cacheTime) throws -> T? {
@@ -153,7 +171,9 @@ public enum DiskStorage {
             do {
                 let data = try Data(contentsOf: fileURL)
                 let obj = try T.fromData(data)
-                metaChangingQueue.async { meta.extendExpiration(with: fileManager, extendingExpiration: extendingExpiration) }
+                metaChangingQueue.async {
+                    meta.extendExpiration(with: fileManager, extendingExpiration: extendingExpiration)
+                }
                 return obj
             } catch {
                 throw KingfisherError.cacheError(reason: .cannotLoadDataFromDisk(url: fileURL, error: error))
@@ -166,10 +186,13 @@ public enum DiskStorage {
 
         func isCached(forKey key: String, referenceDate: Date) -> Bool {
             do {
-                guard let _ = try value(forKey: key, referenceDate: referenceDate, actuallyLoad: false, extendingExpiration: .none) else {
-                    return false
-                }
-                return true
+                let result = try value(
+                    forKey: key,
+                    referenceDate: referenceDate,
+                    actuallyLoad: false,
+                    extendingExpiration: .none
+                )
+                return result != nil
             } catch {
                 return false
             }

+ 26 - 0
Sources/General/KingfisherError.swift

@@ -100,6 +100,8 @@ public enum KingfisherError: Error {
     /// - imageNotExisting: The requested image does not exist in cache. Code 3006.
     /// - cannotConvertToData: Cannot convert an object to data for storing. Code 3007.
     /// - cannotSerializeImage: Cannot serialize an image to data for storing. Code 3008.
+    /// - cannotCreateCacheFile: Cannot create the cache file at a certain fileURL under a key. Code 3009.
+    /// - cannotSetCacheFileAttribute: Cannot set file attributes to a cached file. Code 3010.
     public enum CacheErrorReason {
         
         /// Cannot create a file enumerator for a certain disk URL. Code 3001.
@@ -139,6 +141,22 @@ public enum KingfisherError: Error {
         /// - original: The original image data, if exists.
         /// - serializer: The `CacheSerializer` used for the image serializing.
         case cannotSerializeImage(image: KFCrossPlatformImage?, original: Data?, serializer: CacheSerializer)
+
+        /// Cannot create the cache file at a certain fileURL under a key. Code 3009.
+        /// - fileURL: The url where the cache file should be created.
+        /// - key: The cache key used for the cache. When caching a file through `KingfisherManager` and Kingfisher's
+        ///        extension method, it is the resolved cache key based on your input `Source` and the image processors.
+        /// - data: The data to be cached.
+        /// - error: The underlying error originally thrown by Foundation when writing the `data` to the disk file at
+        ///          `fileURL`.
+        case cannotCreateCacheFile(fileURL: URL, key: String, data: Data, error: Error)
+
+        /// Cannot set file attributes to a cached file. Code 3010.
+        /// - filePath: The path of target cache file.
+        /// - attributes: The file attribute to be set to the target file.
+        /// - error: The underlying error originally thrown by Foundation when setting the `attributes` to the disk
+        ///          file at `filePath`.
+        case cannotSetCacheFileAttribute(filePath: String, attributes: [FileAttributeKey : Any], error: Error)
     }
     
     
@@ -346,6 +364,12 @@ extension KingfisherError.CacheErrorReason {
             return "Cannot serialize an image due to the cache serializer returning `nil`. " +
                    "Image: \(String(describing:image)), original data: \(String(describing: originalData)), " +
                    "serializer: \(serializer)."
+        case .cannotCreateCacheFile(let fileURL, let key, let data, let error):
+            return "Cannot create cache file at url: \(fileURL), key: \(key), data length: \(data.count). " +
+                   "Underlying foundation error: \(error)."
+        case .cannotSetCacheFileAttribute(let filePath, let attributes, let error):
+            return "Cannot set file attribute for the cache file at path: \(filePath), attributes: \(attributes)." +
+                   "Underlying foundation error: \(error)."
         }
     }
     
@@ -359,6 +383,8 @@ extension KingfisherError.CacheErrorReason {
         case .imageNotExisting: return 3006
         case .cannotConvertToData: return 3007
         case .cannotSerializeImage: return 3008
+        case .cannotCreateCacheFile: return 3009
+        case .cannotSetCacheFileAttribute: return 3010
         }
     }
 }