Как я могу получить доступ к текстовому содержимому (kMDItemTextContent) NSMetadataItem в Swift?

Я пытаюсь получить доступ к текстовому представлению результатов NSMetadataQuery с помощью Swift. Однако атрибут kMDItemTextContent, который содержит текстовое представление файла, не существует в результатах. Я могу подтвердить, что атрибут должен существовать, потому что поиск файлов с использованием этого атрибута работает безупречно.

Вот мой код:

import Foundation
import Cocoa

class Indexer {
    public let spotlight = NSMetadataQuery()
    let backgroundQueue = OperationQueue()

    init() {
        let nc = NotificationCenter.default

        spotlight.searchScopes = []
        spotlight.predicate = NSPredicate(fromMetadataQueryString: "kMDItemKind == *")

        nc.addObserver(forName: NSNotification.Name.NSMetadataQueryDidFinishGathering, object: nil, queue: self.backgroundQueue, using:{_ in
            self.spotlight.disableUpdates()
            for i in 0..<self.spotlight.resultCount {
                let result = self.spotlight.result(at: i) as! NSMetadataItem
                print("----- \(result.value(forAttribute: "kMDItemDisplayName") ?? "No title") -----")
                for attribute in result.attributes {
                    print("\(attribute):", result.value(forAttribute: attribute) ?? "No content")
                }
            }
            self.spotlight.enableUpdates()
        })

        spotlight.start()
    }
}

Текущий результат для одного файла выглядит так:

----- n26-csv-transactions.csv -----
kMDItemContentTypeTree: (
    "public.comma-separated-values-text",
    "public.data",
    "public.delimited-values-text",
    "public.plain-text",
    "public.item",
    "public.content",
    "public.text"
)
kMDItemContentType: public.comma-separated-values-text
kMDItemPhysicalSize: 16384
kMDItemDisplayName: n26-csv-transactions.csv
kMDItemKind: CSV Document
kMDItemContentCreationDate: 2019-04-25 17:09:08 +0000
kMDItemContentCreationDate_Ranking: 2019-04-25 00:00:00 +0000
kMDItemContentModificationDate: 2019-04-25 17:09:08 +0000
kMDItemInterestingDate_Ranking: 2019-05-08 00:00:00 +0000
kMDItemUsedDates: (
    "2019-05-07 22:00:00 +0000"
)
kMDItemLastUsedDate: 2019-05-08 10:00:33 +0000
kMDItemLastUsedDate_Ranking: 2019-05-08 00:00:00 +0000
kMDItemUseCount: 3
kMDItemLogicalSize: 591
kMDItemWhereFroms: (
    "https://app.n26.com/download-csv",
    "https://app.n26.com/downloads"
)
kMDItemFSName: n26-csv-transactions.csv
kMDItemFSSize: 591
kMDItemFSCreationDate: 2019-04-25 17:09:08 +0000
kMDItemFSContentChangeDate: 2019-04-25 17:09:08 +0000
kMDItemFSOwnerUserID: 99
kMDItemFSOwnerGroupID: 99
kMDItemFSNodeCount: No content
kMDItemFSInvisible: 0
kMDItemFSTypeCode: 0
kMDItemFSCreatorCode: 0
kMDItemFSFinderFlags: 0
kMDItemFSHasCustomIcon: No content
kMDItemFSIsExtensionHidden: 0
kMDItemFSIsStationery: No content
kMDItemFSLabel: 0

Атрибут kMDItemTextContent здесь отсутствует.

Есть ли способ получить доступ к этому атрибуту, используя NSMetadataItems, возвращаемый Spotlight? Если нет, есть ли другой способ получить доступ к текстовому представлению файла?


person Leo Bernard    schedule 08.05.2019    source источник


Ответы (1)


Есть ли способ получить доступ к этому атрибуту с помощью NSMetadataItems, возвращаемых Spotlight? Если нет, есть ли другой способ получить доступ к текстовому представлению файла?

Одним словом: нет. Прочтите docs по этому атрибуту:

Содержит текстовое представление содержимого документа. Данные в нескольких полях должны быть объединены с использованием пробела в качестве разделителя. Средство импорта Spotlight приложения предоставляет содержимое этого атрибута. Приложения могут создавать запросы с использованием этого атрибута, но не могут напрямую считывать значение этого атрибута. [Выделение мое.]

Информация о текстовом содержании попадает в индекс Spotlight, так что, как вы заметили, вы можете искать по нему. Но вы никаким образом не можете получить его для себя. Он не существует в какой-либо общедоступной форме для программистов.

(Для примера: существующая команда mdls делает в основном то же, что и ваш код — вы можете избавить себя от проблем, запустив mdls в процессе. Что ж, если вы дадите команду mdls в Терминале, вы не увидите kMDItemTextContent перечислены среди атрибутов, даже если содержимое этого файла проиндексировано.)

Чтобы понять, почему это так, подумайте о конфиденциальности. Если бы вы могли прочитать текстовое представление каждого файла на компьютере пользователя только потому, что у вас есть доступ к Spotlight, вы бы знали все данные, находящиеся на компьютере пользователя. Если вы не какой-то злой хакер, вы не должны даже этого хотеть. Чтобы узнать, что находится в файле, откройте файл, если можете.

Так для чего вообще нужен этот атрибут? Это делается для того, чтобы вы могли передать текст в Spotlight в типе файла, который принадлежит вам, с помощью пользовательского импортера Spotlight.

person matt    schedule 08.05.2019
comment
Спасибо! Я не думал об аспекте конфиденциальности, это имеет смысл. - person Leo Bernard; 09.05.2019