如何在不加载资源的情况下获取PHAsset的文件大小?

15

有没有一种方法可以在不使用requestImageDataForAsset或将其转换为ALAsset的情况下获取PHAsset的磁盘文件大小? 我正在加载用户照片库的预览 - 可能有很多成千上万张照片 - 对于我的应用程序来说,他们在导入之前了解文件大小非常重要。

4个回答

31
你可以获取 PHAsset 的 fileSize 并将其转换为易读的形式,方法如下:
      let resources = PHAssetResource.assetResources(for: yourAsset) // your PHAsset

      var sizeOnDisk: Int64? = 0

      if let resource = resources.first {
        let unsignedInt64 = resource.value(forKey: "fileSize") as? CLong
        sizeOnDisk = Int64(bitPattern: UInt64(unsignedInt64!))
      }

然后使用您的sizeOnDisk变量,并将其传递到类似这样的方法中...

func converByteToHumanReadable(_ bytes:Int64) -> String {
     let formatter:ByteCountFormatter = ByteCountFormatter()
     formatter.countStyle = .binary

     return formatter.string(fromByteCount: Int64(bytes))
 }

4
这并没有在任何文档中提到,因为它正在访问头文件。从技术上讲,这是苹果的私有API的一小部分。但是,我们已经提交了一个版本,并且毫无问题地获得了完全的批准。 - Ryan Daulton
@daulSwift 我们如何在 Objective-C 中实现这个? - Omkar Jadhav
这个私钥文件大小会在iOS版本中崩溃吗? - Chandra Lakkimsetty
1
只取第一个项目是否安全?正如苹果所说:“一个资产可以包含多个资源 - 例如,编辑的照片资产包含原始图像和编辑后的图像的资源。” - V.V.V
对于iCloud相册中的视频和图像,我得到的大小为零(0)。 - Ganpat
显示剩余4条评论

4

SWIFT 5.0 轻松简便:

private static let bcf = ByteCountFormatter()

func getSize(asset: PHAsset) -> String {
    let resources = PHAssetResource.assetResources(for: asset)

    guard let resource = resources.first,
          let unsignedInt64 = resource.value(forKey: "fileSize") as? CLong else {
              return "Unknown"
          }

    let sizeOnDisk = Int64(bitPattern: UInt64(unsignedInt64))
    Self.bcf.allowedUnits = [.useMB]
    Self.bcf.countStyle = .file
    return Self.bcf.string(fromByteCount: sizeOnDisk)
}

2

更安全的解决方案:

[asset requestContentEditingInputWithOptions:nil completionHandler:^(PHContentEditingInput * _Nullable contentEditingInput, NSDictionary * _Nonnull info) {
    NSNumber *fileSize = nil;
    NSError *error = nil;
    [contentEditingInput.fullSizeImageURL getResourceValue:&fileSize forKey:NSURLFileSizeKey error:&error];
    NSLog(@"file size: %@\nerror: %@", fileSize, error);
}];

Swift版本:

asset.requestContentEditingInput(with: nil) { (contentEditingInput, _) in
    do {
        let fileSize = try contentEditingInput?.fullSizeImageURL?.resourceValues(forKeys: [URLResourceKey.fileSizeKey]).fileSize
        print("file size: \(String(describing: fileSize))")
    } catch let error {
        fatalError("error: \(error)")
    }
}

如何从PHAsset获取ALAsset URL?的启发。


这个方法太重了。对于成千上万的资产来说行不通。 - SoftDesigner
是的,因此最好在后台线程中执行并缓存结果。 - qiz

2
请尝试这个。
let resources = PHAssetResource.assetResources(for: YourAsset)
var sizeOnDisk: Int64 = 0

if let resource = resources.first {
   let unsignedInt64 = resource.value(forKey: "fileSize") as? CLong
   sizeOnDisk = Int64(bitPattern: UInt64(unsignedInt64!))

   totalSize.text = String(format: "%.2f", Double(sizeOnDisk) / (1024.0*1024.0))+" MB"
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接