2010-05-04 7 views
11

Mi tarea es mostrar los tipos de documentos admitidos en un iPhone con sistema operativo 3.x, como .pdf, .rtf, .doc , .ppt, .png, .tiff, etc.iPhone UIWebView: loadData no funciona con ciertos tipos (Excel, MSWord, PPT, RTF)

Ahora, he guardado estos archivos cifrados sólo se en el disco. Por razones de seguridad, quiero evitar almacenarlos sin cifrar en el disco.

Por lo tanto, yo prefiero usar loadData:MIMEType:textEncodingName:baseURL: en lugar de loadRequest: para mostrar el documento porque loadData me permite pasar el contenido de un objeto NSData, es decir, que pueda descifrar el archivo en la memoria y no tienen necesidad de almacenarlo en el disco, como sería necesario cuando se usa loadRequest.

El problema es que loadData no parece trabajar con todos los tipos de archivos:

Las pruebas muestran que todos los tipos de imágenes parecen funcionar PDF finas, así como, mientras que los tipos más complejos no lo hacen. Llego a errores tales como:

NSURLErrorDomain Code=100 
NSURLErrorDomain Code=102 

WebView parece necesitar una URL verdaderamente trabajar para acceder a los documentos como un archivo, a pesar de que me ofrecía todo el contenido a través del objeto NSData ya.

Aquí está el código que utilizo para mostrar el contenido:

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

El tipo MIME se establece correctamente, por ejemplo, a "application/msword" para archivos .doc.

¿Alguien sabe cómo podría obtener loadData para trabajar con todos los tipos que admite loadRequest? O, como alternativa, ¿hay alguna manera de saber qué tipos funcionan con seguridad (es decir, sancionado oficialmente por Apple) con loadData? Entonces puedo trabajar dos veces, creando un archivo temporal no cifrado solo para aquellos casos que loadData no le gustará.

actualización

Parece que no soy el primero que se ejecuta en esto. Ver aquí:

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

lo tanto, supongo, que es el status quo, y nada de lo que puede hacer al respecto.

Alguien sugirió una solución alternativa que podría trabajar, sin embargo:

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

Básicamente, la idea es proporcionar un pequeño servidor HTTP que sirve el archivo (de memoria en mi caso), y luego use loadRequest. Sin embargo, esto probablemente requiera un poco más de memoria, ya que tanto el servidor como la vista web probablemente mantendrán todo el contenido en la memoria como dos copias, en lugar de usar loadData, donde ambos preferirían compartir el mismo objeto de datos. (Tenga en cuenta que tendré que guardar los datos descifrados en la memoria, ese es el punto aquí).

+1

También he experimentado rarezas cuando se trabaja con archivos que no son html en 'UIWebView'. Me temo que parece que 'UIWebView', entre otras cosas, mira la URL del archivo que intenta cargar. Cargar con un archivo temporal no encriptado con una URL de archivo podría ser tu única salida "segura" (hasta donde yo sé). – alleus

Respuesta

8

Experimenté un problema muy similar (sin embargo, recibí mis archivos de un servidor) y vi tu publicación y pensé que era un callejón sin salida y luego por casualidad comencé a experimentar con el dispositivo (iPad, en este caso) y funcionó cuando le di al baseURL lo que solía obtener del servidor y funcionó, pero no funciona en el simulador. Intentaría eso, de lo contrario enviaría un informe de error a Apple.

+1

Acabo de probar esto en un dispositivo iPhone 4 y sigue sin mostrar un archivo del tipo "application/msword". Sin embargo, quizás pase el tipo incorrecto. ¿Qué tipo de datos específicos funcionó para ti? –

+3

¡Ah! Es importante establecer un baseURL no nulo. Con eso, ahora incluso funciona con msword archivos en el simulador, ejecutando iOS 4.0 o 3.2, así como en mi iPhone4 y iPad. Ahora necesito un dispositivo OS 3.0 para comprobar si esto también funciona allí ahora. Desafortunadamente, actualicé mi iPod Touch a 4.0 recientemente. Estúpido movimiento, ahora resulta. ¡En cualquier caso, acaba de obtener sus primeros puntos en SO! Bienvenido :) –

+0

Resulta que esta es probablemente una nueva "característica", o mejor dicho, corrección de errores, introducida en iOS 3.2. Por lo tanto, si está soportando iOS 3.1.3 o posterior, aún necesita crear un caso especial para los tipos y escribir archivos temporales para los tipos de archivos complejos mencionados anteriormente. –

0

Aquí está la solución a través de 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() { 
    } 
} 

Ahora sólo tiene que registrarse clase:

NSURLProtocol.registerClass(CoreDataFileURLProtocol.self) 

Y crear una solicitud con file_id:

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