Search code examples
iosswiftpdfwebviewnsdocumentdirectory

Unable to load pdf from document directory in Swift


I have downloaded a pdf from remote server and saved it in document directory. Now I'm trying to retrieve it and display the pdf in the webView but I keep getting this exception:

failed to find PDF header: `%PDF' not found.

before this exception it showing this exception as well:

objc[8087]: Class PLBuildVersion is implemented in both /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/AssetsLibraryServices.framework/AssetsLibraryServices (0x11f29dcc0) and /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/PhotoLibraryServices.framework/PhotoLibraryServices (0x11f0b46f0).

One of the two will be used. Which one is undefined.

But I have noticed that when I try to run from mobile instead of emulator then this second exception is gone. Below is my code for fetching it:

    let check:String =  FileNames[0] + ".pdf"
      print("check = \(check)")
 // Method 1
        let docURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let targetURL = docURL.appendingPathComponent(check)
       
        var request = URLRequest(url: targetURL)
        webView.loadRequest(request)

    /*
           // Method 2
       var pdfURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! as URL
        pdfURL = pdfURL.appendingPathComponent(check) as URL
        print("check url = \(pdfURL)")
        let data = try! Data(contentsOf: pdfURL)
        print("check data = \(data)")
        webView.load(data, mimeType: "application/pdf", textEncodingName:"utf-8", baseURL: pdfURL) // pdfURL.deletingLastPathComponent()
      */
        
        //let requestk = NSURLRequest(url: pdfURL as URL)
       // webView.loadRequest(requestk as URLRequest)
        
        
         // Method 3
        
      /*  let fileManager = FileManager.default
        let documentsUrl = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0] as NSURL
        
        var pdf = documentsUrl.appendingPathComponent(check)
        print("check item fetching from documentsUrl = \(pdf)")
        let req = NSURLRequest(url: pdf!)
        self.webView.loadRequest(req as URLRequest)
      */  

I have searched a lot about this exception and followed all the possible solutions but none of it is working. But if I try to display this pdf directly from the remote server's address it is getting displayed. And also I have checked that this pdf is stored correctly. I have tried loading through both webView.loadRequest and webView.load with data method, maybe I'm missing something small.

Update

  var pdfURL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)).last! as URL
        print("check final = \(pdfURL)")
        pdfURL = pdfURL.appendingPathComponent(check) as URL
        
        do{
            let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
            let url = URL(fileURLWithPath: path)
            var filePath = url.appendingPathComponent(check).path
            let fileManager1 = FileManager.default
            if fileManager1.fileExists(atPath: filePath) {
                print("FILE AVAILABLE in VC")
              // let fileUrlkk = NSURL(string: filePath)// converting string into URL
                
                filePath = "file://\(filePath)"
                
                let fileUrlkk = Foundation.URL(string: filePath)
                let data = try Data(contentsOf: fileUrlkk!)

               //  let data = try Data(contentsOf: pdfURL) // tried but didn’t work


                self.webView.load(data, mimeType: "application/pdf", textEncodingName:"", baseURL: pdfURL.deletingLastPathComponent())                   
                
            } else {
                print("FILE NOT AVAILABLE in VC")
            }
        }
        catch let error as NSError {
            print("An error took place: \(error)")
        }

it displays "FILE AVAILABLE in VC" but still with this exception.


Solution

  • Use below code to load PDF in WebView

    Swift 3.0

    var pdfURL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)).last! as URL
    pdfURL = pdfURL.appendingPathComponent("Swift.pdf") as URL
    
    let data = try! Data(contentsOf: pdfURL)
    self.webView.load(data, mimeType: "application/pdf", textEncodingName:"", baseURL: pdfURL.deletingLastPathComponent())
    

    Where pdf file store in Document directory here is the path.

    /Documents/Swift.pdf

    ----- UPDATE ------

    1. Create new project.
    2. Drag 1 sample PDF in bundle "sample.pdf"
    3. And change your controller code with below
    4. that's it run

    import UIKit

    class ViewController: UIViewController {

    @IBOutlet weak var webView: UIWebView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        let check = "Swift.pdf"
    
        var pdfURL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)).last! as URL
        print("check final = \(pdfURL)")
        pdfURL = pdfURL.appendingPathComponent(check) as URL
    
        if let pdfBundleURL = Bundle.main.url(forResource: "sample", withExtension: "pdf", subdirectory: nil, localization: nil)  {
            do {
                let data = try Data(contentsOf: pdfBundleURL)
    
                //Lastly, write your file to the disk.
                try data.write(to: pdfURL, options: .atomicWrite)
    
            }
            catch {
                // catch errors here
            }
        }
    
        do{
            let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
            let url = URL(fileURLWithPath: path)
            var filePath = url.appendingPathComponent(check).path
            let fileManager1 = FileManager.default
            if fileManager1.fileExists(atPath: filePath) {
                print("FILE AVAILABLE in VC")
                // let fileUrlkk = NSURL(string: filePath)// converting string into URL
    
                filePath = "file://\(filePath)"
    
                let fileUrlkk = Foundation.URL(string: filePath)
                let data = try Data(contentsOf: fileUrlkk!)
    
                //  let data = try Data(contentsOf: pdfURL) // tried but didn’t work
    
    
                self.webView.load(data, mimeType: "application/pdf", textEncodingName:"", baseURL: pdfURL.deletingLastPathComponent())
    
            } else {
                print("FILE NOT AVAILABLE in VC")
            }
        }
        catch let error as NSError {
            print("An error took place: \(error)")
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    

    }