Swift,如何从“何处"获取图像?元数据字段? [英] Swift, how to get an image "where from" metadata field?

查看:56
本文介绍了Swift,如何从“何处"获取图像?元数据字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从macOS上的文件系统读取文件,我尝试使用以下代码提取元数据:

I'm reading a file from the file system on macOS, I tried to extract the metadata with the following code:

let imagedata = try? Data(contentsOf: fileUrl)

if imagedata == nil {
    print("Could not read contents of image")
    return
}

var source: CGImageSource = CGImageSourceCreateWithData((imagedata as! CFMutableData), nil)!
var metadata = CGImageSourceCopyPropertiesAtIndex(source, 0, nil) as? [AnyHashable: Any]

print("image metadata", metadata)

这是我得到的输出:

image metadata Optional([AnyHashable("ColorModel"): RGB, AnyHashable("DPIHeight"): 72, AnyHashable("PixelHeight"): 840, AnyHashable("ProfileName"): sRGB IEC61966-2.1, AnyHashable("PixelWidth"): 840, AnyHashable("{PNG}"): {
    Chromaticities =     (
        "0.3127",
        "0.329",
        "0.64",
        "0.33",
        "0.3",
        "0.6000000000000001",
        "0.15",
        "0.06"
    );
    Gamma = "0.45455";
    InterlaceType = 0;
    XPixelsPerMeter = 2834;
    YPixelsPerMeter = 2834;
    sRGBIntent = 0;
}, AnyHashable("DPIWidth"): 72, AnyHashable("Depth"): 8])

然后提取出通常的元数据,但是当我将图像拖放到桌面然后右键单击并获取信息时,我实际上想知道从何处下载图像.,我看到了该字段:

And that extracts the usual metadata, but I actually would like to know where the image was downloaded from, when I drag n' drop an image into the desktop and then right click and then get info, I see the field:

有什么方法可以检索此字段?

Is there any way to retrieve this field?

我尝试过:

if let attr = try? FileManager.default.attributesOfItem(atPath: fileUrl.path) {
    print("attributes", attr)
}

现在我可以看到 kMDItemWhereFroms 字段,但是我不知道如何到达或解析它.也许有人在这里有个主意?

and now I can see the kMDItemWhereFroms field, but I don't know how to reach it or parse. Maybe someone has an idea here?

推荐答案

我总是很高兴展示如何修补,如何查找数据,所以我将展示如何获得数据,而我却不知道一切.

I think it's always nice to show how tinker, how to find the data, so I'll show how I got it, while I didn't know at all about it.

首先想到的是,它可能不在图像元数据中,而在文件系统"中,因此让我们看一下FileManager.它位于 FileManager.attributesOfItem(atPath:)

First thought, it might not be in image Metadata, but in "File System" ones, so let's look at FileManager. It's in FileManager.attributesOfItem(atPath:)

第1步:

let attributes = try fileManager.attributesOfItem(atPath: filePath)

这给了我

[__C.NSFileAttributeKey(_rawValue: NSFileGroupOwnerAccountName): staff, 
__C.NSFileAttributeKey(_rawValue: NSFileReferenceCount): 1, 
__C.NSFileAttributeKey(_rawValue: NSFileModificationDate): 2020-05-13 15:16:20 +0000, 
__C.NSFileAttributeKey(_rawValue: NSFileSystemFileNumber): 8635383780, 
__C.NSFileAttributeKey(_rawValue: NSFilePosixPermissions): 420, 
__C.NSFileAttributeKey(_rawValue: NSFileType): NSFileTypeRegular, 
__C.NSFileAttributeKey(_rawValue: NSFileOwnerAccountID): 501, 
__C.NSFileAttributeKey(_rawValue: NSFileGroupOwnerAccountID): 20, 
__C.NSFileAttributeKey(_rawValue: NSFileExtensionHidden): 0, 
__C.NSFileAttributeKey(_rawValue: NSFileHFSTypeCode): 0, 
__C.NSFileAttributeKey(_rawValue: NSFileCreationDate): 2020-05-13 15:16:20 +0000, 
__C.NSFileAttributeKey(_rawValue: NSFileOwnerAccountName): Larme, 
__C.NSFileAttributeKey(_rawValue: NSFileSize): 1258299, 
__C.NSFileAttributeKey(_rawValue: NSFileSystemNumber): 16777220, 
__C.NSFileAttributeKey(_rawValue: NSFileExtendedAttributes): {
    "com.apple.lastuseddate#PS" = {length = 16, bytes = 0x440fbc5e00000000503f091700000000};
    "com.apple.macl" = {length = 72, bytes = 0x02009685 15175d5d 47089537 71b6a786 ... 00000000 00000000 };
    "com.apple.metadata:kMDItemDownloadedDate" = {length = 53, bytes = 0x62706c69 73743030 a1013341 c2362362 ... 00000000 00000013 };
    "com.apple.metadata:kMDItemWhereFroms" = {length = 414, bytes = 0x62706c69 73743030 a201025f 11013b68 ... 00000000 00000178 };
    "com.apple.quarantine" = {length = 57, bytes = 0x30303833 3b356562 63306634 343b5361 ... 44344445 45343845 };
}, __C.NSFileAttributeKey(_rawValue: NSFileHFSCreatorCode): 0]

查看此信息的内容:

[...
__C.NSFileAttributeKey(_rawValue: NSFileExtendedAttributes): {
...
    "com.apple.metadata:kMDItemWhereFroms" = {length = 414, bytes = 0x62706c69 73743030 a201025f 11013b68 ... 00000000 00000178 };
...
]

好吧,让我们继续第2步,让我们更深入:

Ok, so let's continue to step 2, let's dig deeper:

let extendedAttributes = attributes[FileAttributeKey(rawValue: "NSFileExtendedAttributes")] as! [String: Any]
let data = extendedAttributes["com.apple.metadata:kMDItemWhereFroms"] as! Data //that's the new output for `Data` in new systems (iOS13+, etc.)

一如既往,我倾向于以防万一以获取更多信息: let str = String(data:data,encoding:.utf8)返回nil.让我们记住,并非所有数据都可以像这样转换为utf8字符串.例如,一张图片将无法制作.

As always, I tend to do just in case to get more info: let str = String(data: data, encoding: .utf8) which returns nil. Let's remember that not all data is convertible into utf8 string like that. For instance, an image won't make it.

但是我知道一些技巧,让我们去做: let str = String(data:data,encoding:.ascii),这给了我:

But I know a few tricks, let's do instead: let str = String(data: data, encoding: .ascii), this gives me:

"bplist00¢\u{01}\u{02}_\u{11}\u{01};https://doc-04-6k-docs.googleusercontent.com/docs/securesc/teo5l5s1g996hre86q7qv786r7me56c3/3nneqai4sh4lvk3bdlnpokt8793t4t5t/1589382975000/11847256646728493158/11847256646728493158/0B1U9OypmOvxpODVFb2VGZEdpckk?e=download&authuser=0&nonce=faav7fnl402re&user=11847256646728493158&hash=vl51p8m313rnnao3dleqsl348rp2vo82_\u{10}+https://drive.google.com/drive/u/0/my-drive\0\u{08}\0\u{0B}\u{01}J\0\0\0\0\0\0\u{02}\u{01}\0\0\0\0\0\0\0\u{03}\0\0\0\0\0\0\0\0\0\0\0\0\0\0\u{01}x"

我从Google云端硬盘下载了示例,信息似乎很有意义.在那里看到了什么?: bplist ,这是这里最重要的一个.

I downloaded my sample from my Google Drive, info seems making sense. What do see there?: bplist, that's the most important one here.

属性列表?然后将其解码:

A PropertyList? Let's decode it then:

let urls = try PropertyListDecoder().decode([String].self, from: data)

成为一个 [String] 对我来说很有意义,这会有所不同,那就更难了.但这很简单.

It made sense for me to be a [String], it would have been different, that would had be harder. But it's a simple one.

最终代码:

static func downloadedFromURLs(for filePath: String) -> [String]? {
    let fileManager = FileManager.default
    guard fileManager.fileExists(atPath: filePath) else { print("File doesn't exists"); return nil }

    do {
        let attributes = try fileManager.attributesOfItem(atPath: filePath)
        guard let extendedAttributes = attributes[FileAttributeKey(rawValue: "NSFileExtendedAttributes")] as? [String: Any] else {
            print("Didn't find NSFileExtendedAttributes value")
            return nil
        }
        guard let data = extendedAttributes["com.apple.metadata:kMDItemWhereFroms"] as? Data else {
            print("Didn't find com.apple.metadata:kMDItemWhereFroms value")
            return nil
        }
        let urls = try PropertyListDecoder().decode([String].self, from: data)
        return urls
    } catch {
        print("Error: \(error)")
        return nil
    }
}

旁注:可能会有一些常量而不是为"com.apple.metadata:kMDItemWhereFroms" 编写硬编码的字符串和 NSFileExtendedAttributes ,但在此处没看到它

Side note: There might be some constant instead of writing hard coded strings for "com.apple.metadata:kMDItemWhereFroms" and NSFileExtendedAttributes, but I didn't see it here.

一些相关的感兴趣的讨论. https://apple.stackexchange.com/questions/110239/where-is-the-the-the-the-where-from-meta-data-stored-when-downloaded viaviachrome

Some related interested discussion. https://apple.stackexchange.com/questions/110239/where-is-the-where-from-meta-data-stored-when-downloaded-via-chrome

这篇关于Swift,如何从“何处"获取图像?元数据字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆