2010-05-04 8 views
11

Il mio compito è visualizzare i tipi di documenti supportati su un iPhone con OS 3.x, come .pdf, .rtf, .doc , .ppt, .png, .tiff ecciPhone UIWebView: loadData non funziona con determinati tipi (Excel, MSWord, PPT, RTF)

Ora, ho conservato questi file solo cifrato su disco. Per motivi di sicurezza, voglio evitare di archiviarli in modo non criptato su disco.

Quindi, io preferisco usare loadData:MIMEType:textEncodingName:baseURL: invece di loadRequest: per visualizzare il documento perché loadData mi permette di passare il contenuto in un oggetto NSData, cioè posso decifrare il file in memoria e non hanno bisogno di memorizzarlo su disco, come sarebbe necessario quando si utilizza loadRequest.

Il problema è che loadData non sembra funzionare con tutti i tipi di file:

test dimostra che tutti i tipi di immagine sembrano funzionare bene, così come file PDF, mentre i tipi più complessi non lo fanno. Ottengo un errore come ad esempio:

NSURLErrorDomain Code=100 
NSURLErrorDomain Code=102 

WebView sembra aver bisogno di un URL veramente lavorare per l'accesso ai documenti in un file, nonostante mi offre tutti i contenuti tramite l'oggetto NSData già.

Ecco il codice che uso per visualizzare il contenuto:

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

Il mime-type è impostato correttamente, per esempio a "application/msword" per i file .doc.

Qualcuno sa come posso ottenere loadData per funzionare con tutti i tipi che loadRequest supporta? O, in alternativa, c'è un modo in cui posso dire quali tipi funzionano di sicuro (cioè sanzionato ufficialmente da Apple) con loadData? Quindi posso lavorare su due livelli, creando un file temporaneo non crittografato solo per quei casi che loadData non piacerà.

Aggiornamento

Sembra che io non sono il primo in esecuzione in questo. Vedi qui:

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

Quindi, credo, che sia lo status quo, e niente che possa fare al riguardo.

Qualcuno ha suggerito una soluzione alternativa, che potrebbe funzionare, però:

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

In sostanza, l'idea è quella di fornire un server http minuscolo che serve il file (dalla memoria nel mio caso), e poi usa loadRequest. Probabilmente questo è un po 'più carico di memoria, poiché sia ​​il server che la webview probabilmente terranno l'intero contenuto in memoria come due copie, invece di usare loadData, dove entrambi preferiscono condividere lo stesso oggetto dati. (Intendiamoci, dovrò tenere in memoria i dati decrittografati, questo è il punto qui).

+1

Ho anche sperimentato stranezze quando si lavora con file non html in 'UIWebView'. Purtroppo temo che 'UIWebView' tra l'altro guarda l'URL del file che sta tentando di caricare. Il caricamento con un file temporaneo non crittografato con un URL di file potrebbe essere la tua unica via di uscita "sicura" (per quanto ne so). – alleus

risposta

8

Ho riscontrato un problema molto simile (ho comunque ricevuto i miei file da un server) e ho visto il tuo post e ho pensato che fosse un vicolo cieco e quindi per caso ho iniziato a sperimentare sul dispositivo (iPad, in questo caso) e ha funzionato quando ho dato la baseURL come quello che ho usato per ottenerlo dal server e ha funzionato, ma non funziona sul simulatore. Ci proverei, altrimenti manderei un bug report ad Apple.

+1

Ho appena provato questo su un dispositivo iPhone 4 e non riesce ancora a mostrare un file di tipo "application/msword". Forse ho appena passato il tipo sbagliato, comunque. Quale tipo + dati specifici ha funzionato per te? –

+3

Ah! È importante impostare un valore base non zero. Con ciò, ora funziona anche con i file msword nel simulatore, con iOS 4.0 o 3.2, nonché con il mio iPhone4 e iPad. Ora ho bisogno di un dispositivo OS 3.0 per verificare se ora funziona anche lì. Purtroppo, ho aggiornato il mio iPod Touch a 4.0 di recente. Mossa stupida, ora si scopre. In ogni caso, hai appena guadagnato i tuoi primi punti su SO! Benvenuto :) –

+0

Si scopre che questa è probabilmente una nuova "funzionalità", o piuttosto una bugfix, introdotta in iOS 3.2. Quindi, se stai supportando iOS 3.1.3 o versioni precedenti, hai ancora bisogno di casi speciali dei tipi e scrivi un file temporaneo per i tipi di file complessi sopra menzionati. –

0

Ecco la soluzione via 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() { 
    } 
} 

Ora è necessario solo registrarsi classe:

NSURLProtocol.registerClass(CoreDataFileURLProtocol.self) 

E creare una richiesta con file_id:

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