Saltar al contenido

Descargar PDF incrustado cargado en WKWebView

Bienvenido a nuestro espacio, en este sitio vas a encontrar la resolución que estabas buscando.

Solución:

Actualizar

De los Docs dicen

La API Fetch proporciona una interfaz para buscar recursos (incluso a través de la red). A cualquiera que haya utilizado XMLHttpRequest le resultará familiar

También puede utilizar lo siguiente string para obtener la cadena base64 de WKWebview

 let s = "path = document.getElementById("plugin").srcn" +
        "n" +
        "fetch(path).then(function (response) n" +
        " response.body.getReader().read().then(function(result) n" +
        " return btoa(String.fromCharCode.apply(null, result.value));n" +
        " ).then(function(b64) n" +
        " window.webkit.messageHandlers.myInterface.postMessage(b64);n" +
        " );n" +
        ");"

tanto fetch como xmlhttp funcionan de forma asincrónica … todo lo que necesita hacer es esperar cuando se complete el procesamiento, pasarlo al Swift usando el puente de javascript a ios (WKScriptMessageHandler)

Utilice el siguiente código para obtener la base64 string de javascript a Swift. Estoy usando WKScriptMessageHandler para obtener la devolución de llamada de Javascript cuando la base64 string está listo para ser consumido. En String s, solo necesita pasar la URL del pdf y hará una solicitud ajax para obtener el archivo pdf y luego convertirlo a base64 string.

import UIKit
import WebKit
class ViewController: UIViewController 
    @IBOutlet weak var btnPDF: UIButton!
    @IBOutlet weak var webViewParentView: UIView!
    var activityIndicator: UIActivityIndicatorView?
    var webView: WKWebView!
    @objc func didSelect(_ sender: UIView)
        let s="var xhr = new XMLHttpRequest();n" +
            "xhr.open('GET', "https://codingexceptions.com/wkwebview/dummy.pdf", true);n" +
            "n" +
            "xhr.responseType = 'arraybuffer';n" +
            "n" +
            "xhr.onload = function(e) n" +
            " if (this.status == 200) n" +
            " var uInt8Array = new Uint8Array(this.response);n" +
            " var i = uInt8Array.length;n" +
            " var binaryString = new Array(i);n" +
            " while (i--)n" +
            " n" +
            " binaryString[i] = String.fromCharCode(uInt8Array[i]);n" +
            " n" +
            " var data = binaryString.join('');n" +
            "n" +
            " var base64 = window.btoa(data);n" +
            "n" +
            "window.webkit.messageHandlers.myInterface.postMessage(base64);" +
            "n" +
            " n" +
            ";n" +
            "n" +
        "xhr.send();n"
        webView.configuration.userContentController.add(self, name: "myInterface")
        webView?.evaluateJavaScript(s, completionHandler: (string,error) in
            print(error ?? "no error")
        )
    
    func setupWebView()
        webView = WKWebView.init(frame: CGRect(x: 0, y: 0, width: webViewParentView.frame.width, height: webViewParentView.frame.height))
        webView.navigationDelegate = self
        webViewParentView.addSubview(webView)
        activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
        activityIndicator?.center = self.view.center
        self.view.addSubview(activityIndicator!)
        webView.load(URLRequest(url: URL(string: "https://codingexceptions.com/wkwebview/index.php")!))
        activityIndicator?.startAnimating()
    

    override func viewDidLoad() 
        super.viewDidLoad()
        btnPDF.addTarget(self, action: #selector(self.didSelect(_:)), for: .touchUpInside)

    
    override func viewDidAppear(_ animated: Bool) 
        super.viewDidAppear(animated)
         setupWebView()
    

extension ViewController: WKScriptMessageHandler
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) 
         print("Message received: (message.name) with body: (message.body)")
    

extension ViewController: WKNavigationDelegate
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) 
        self.activityIndicator?.stopAnimating()
        self.activityIndicator?.removeFromSuperview()
        self.activityIndicator = nil
    

Actualización: para obtener la fuente de la etiqueta de inserción como se indica en la respuesta de @ Tarun

solo pon lo de abajo línea en el comienzo de string variable s y pasar la URL en xhr.open

var url = document.getElementById("plugin").src

PD: usando la respuesta como comentarios, ya que necesito formatear

Debe ejecutar el siguiente JavaScript en la vista web

path = document.getElementById("plugin").src

fetch(path).then(function (response) 
    response.body.getReader().read().then(function(result) 
        return btoa(String.fromCharCode.apply(null, result.value));
    ).then(function(b64) 
        window.pdf_data = b64;
    );
);

Luego puede ejecutar otra consulta para acceder al window.pdf_data asumiendo que es posible obtener el valor de retorno de una ejecución de javascript?

Esta pregunta se hace a veces de vuelta, pero si alguien busca rápido solución con WKWebView para descargar .pdf o cualquier archivo en el Administrador de archivos, así es como terminé

class WebPortalVC: UIViewController, WKNavigationDelegate,WKUIDelegate, UIDocumentInteractionControllerDelegate,URLSessionDownloadDelegate {

anular la siguiente función, que interceptará la URL, en nuestro caso verificamos ulr que termina con .pdf y .csv y lo redireccionamos para abrir con la vista del administrador de archivos. que permiten ver archivos, descargar y guardar en el almacenamiento del dispositivo, airdrop o compartir con otras aplicaciones

simplemente agregue las siguientes funciones y verifique.

 func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) 
    if let url = navigationAction.request.url 

    decisionHandler(.allow)


func downloadPDF(tempUrl:String)
    print("fileDownload: downloadPDF")
    guard let url = URL(string: tempUrl) else  return 
    let urlSession = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue())
    let downloadTask = urlSession.downloadTask(with: url)
    downloadTask.resume()
    //showHUD(isShowBackground: true); //show progress if you need

func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController 
    print("fileDownload: documentInteractionControllerViewControllerForPreview")
    return self

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) 
    // create destination URL with the original pdf name
    print("fileDownload: urlSession")
    guard let url = downloadTask.originalRequest?.url else  return 
    print("fileDownload: urlSession (url)")
    let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let destinationURL = documentsPath.appendingPathComponent(url.lastPathComponent)
    // delete original copy
    try? FileManager.default.removeItem(at: destinationURL)
    // copy from temp to Document
    do 
        try FileManager.default.copyItem(at: location, to: destinationURL)
        myViewDocumentsmethod(PdfUrl:destinationURL)
        print("fileDownload: downloadLocation", destinationURL)
        DispatchQueue.main.async 
            NBMaterialToast.showWithText(self.view, text: "Download Completed", duration: NBLunchDuration.long)
        
     catch let error 
        print("fileDownload: error (error.localizedDescription)")
    
   // dismissHUD(isAnimated: false); //dismiss progress

func myViewDocumentsmethod(PdfUrl:URL)
    print("fileDownload: myViewDocumentsmethod (PdfUrl)")
    DispatchQueue.main.async 
        let controladorDoc = UIDocumentInteractionController(url: PdfUrl)
        controladorDoc.delegate = self
        controladorDoc.presentPreview(animated: true)
    

Aquí tienes las comentarios y calificaciones

Si te sientes suscitado, tienes la libertad de dejar una noticia acerca de qué te ha gustado de esta reseña.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *