iPhone UIWebView: loadData не работает с определенными типами (Excel, MSWord, PPT, RTF) - PullRequest
11 голосов
/ 04 мая 2010

Моя задача - отобразить поддерживаемые типы документов на iPhone с ОС 3.x, например .pdf, .rtf, .doc, .ppt, .png, .tiff и т. Д.

Теперь я сохранил эти файлы только зашифрованные на диске. Из соображений безопасности я хочу не хранить их в незашифрованном виде на диске.

Следовательно, я предпочитаю использовать loadData:MIMEType:textEncodingName:baseURL: вместо loadRequest: для отображения документа, потому что loadData позволяет мне передавать содержимое в объект NSData, т.е. я могу расшифровать файл в памяти и не нужно хранить это на диске, как это потребуется при использовании loadRequest.

Проблема в том, что loadData не работает со всеми типами файлов:

Тестирование показывает, что все типы изображений, как и PDF, работают нормально, а более сложные типы - нет. Я получаю ошибки, такие как:

NSURLErrorDomain Code=100
NSURLErrorDomain Code=102

Похоже, что WebView нужен действительно рабочий URL для доступа к документам в виде файла, несмотря на то, что я уже предлагал весь контент через объект NSData.

Вот код, который я использую для отображения содержимого:

[webView loadData:data MIMEType:type textEncodingName:@"utf-8" baseURL:nil];

MIME-тип установлен правильно, например, в "application / msword" для файлов .doc.

Кто-нибудь знает, как заставить loadData работать со всеми типами, которые поддерживает loadRequest? Или, альтернативно, есть ли какой-то способ, которым я могу сказать, какие типы работают наверняка (то есть официально разрешено Apple) с loadData? Тогда я могу работать в два раза, создавая временный незашифрованный файл только для тех случаев, которые не нравятся loadData.

Обновление

Похоже, я не первый, кто сталкивается с этим. Смотрите здесь:

http://osdir.com/ml/iPhoneSDKDevelopment/2010-03/msg00216.html

Итак, я полагаю, это статус-кво, и я ничего не могу с этим поделать.

Кто-то предложил обходной путь, который может работать, хотя:

http://osdir.com/ml/iPhoneSDKDevelopment/2010-03/msg00219.html

По сути, идея состоит в том, чтобы предоставить крошечный http-сервер, который обслуживает файл (из памяти в моем случае), а затем использовать loadRequest. Это, вероятно, немного более интенсивно использует память, так как и сервер, и веб-представление, вероятно, оба хранят все содержимое в памяти как две копии, в отличие от использования loadData, где оба предпочитают использовать один и тот же объект данных. (Имейте в виду, мне придется хранить расшифрованные данные в памяти, вот и весь смысл).

Ответы [ 2 ]

8 голосов
/ 30 июня 2010

У меня возникла очень похожая проблема (однако я получаю свои файлы с сервера), я увидел ваш пост и подумал, что это тупик, а затем просто случайно начал экспериментировать на устройстве (в данном случае iPad) работал, когда я дал baseURL как то, что я использовал, чтобы получить его с сервера, и он работал, но не работает на симуляторе. Я бы попробовал это, иначе я бы отправил отчет об ошибке в Apple.

0 голосов
/ 03 ноября 2014

Вот решение через NSURLProtocol:

class CoreDataFileURLProtocol : NSURLProtocol {
    var connection: NSURLConnection!

    override class func canInitWithRequest(request: NSURLRequest) -> Bool {
        return (request.URL.scheme == "coredatafile")
    }

    override class func canonicalRequestForRequest(request: NSURLRequest) -> NSURLRequest {
        return request
    }

    override func startLoading() {
        if let file_id = self.request.URL.absoluteString?.lastPathComponent {
            if let file = SAFile.MR_findFirstByAttribute("file_id", withValue: file_id) as? SAFile {
                let response = NSURLResponse(URL: request.URL, MIMEType: file.mime, expectedContentLength: Int(file.filesize), textEncodingName: "utf-8")
                client?.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .NotAllowed)
                client?.URLProtocol(self, didLoadData: file.data)
                client?.URLProtocolDidFinishLoading(self)
            }
        }
    }

    override func stopLoading() {
    }
}

Теперь вам нужно только зарегистрировать класс:

NSURLProtocol.registerClass(CoreDataFileURLProtocol.self)

И создайте запрос с помощью file_id:

let url = NSURL(scheme: "coredatafile", host: "myapp.com", path: "/\(file.file_id)")
webView.loadRequest(NSURLRequest(URL: url!))
...