Search code examples
iosswiftpdfalamofirensfilemanager

PDF File reading Issue only on Offline mode swift


I have successfully Implemented downloading mechanism for pdf files. Files are downloading and save to document directory of simulator. Issue is when I try to disconnect internet the files locally stored not accessible. In my application I have two modes Online and Offline. In Online mode I store data and its accessible at Offline mode. Only problem is getting with pdf files.

How to access pdf files in offline mode?

viewController Code:

let fileType = (URL != nil) ? ".pdf" : ".png"
DataProvider.main.downloadFile(url: String(describing: self.URL!), filetype: fileType, callback: { success, response in

            if !success || response == nil {
                return false
            }
            if((response as! String).hasSuffix("pdf")){

                self.imageScrollView.isHidden = true
                self.contentContainer.isHidden = false
                self.document = ReaderDocument(filePath:(response as! String).removingPercentEncoding, password: nil)
                self.loadDocument()

                self._contentView.removeFromSuperview()
                self._contentView.frame = self.contentContainer.bounds
                self.contentContainer.addSubview(self._contentView)
            }else if (FileManager.default.fileExists(atPath: (response as! String).removingPercentEncoding!) ){
                self.imageScrollView.isHidden = false
                self.contentContainer.isHidden = true
                let image = UIImage(contentsOfFile:(response as! String).removingPercentEncoding!)!
                self.imageScrollView.display(image)
            }
            return true
        })

DataProvider Class with custom directory:

@objc public func downloadFile(url:String, filetype: String, callback:@escaping (_ success:Bool, _ result:Any?)->(Bool)) -> Void {
        var destination = DownloadRequest.suggestedDownloadDestination(for: .documentDirectory)
        if filetype.elementsEqual(".pdf"){
            destination = { _, _ in
                let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
                let fileURL = documentsURL.appendingPathComponent(String(abs(url.hashValue)) + ".pdf") //giving different name to file
                return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
            }
        }

        Alamofire.download(
            url,
            method: .get,
            parameters: nil,
            encoding: JSONEncoding.default,
            headers: [ "Accept":"*/*", "Authorization":"Bearer \(token ?? "")"],
            to: destination).downloadProgress(closure: { (progress) in
                //progress closure
                print(progress)
            }).response(completionHandler: { (DefaultDownloadResponse) in
                //here you able to access the DefaultDownloadResponse
                //result closure
                callback(DefaultDownloadResponse.response?.statusCode == 200, DefaultDownloadResponse.destinationURL?.absoluteString.replacingOccurrences(of: "file://", with: ""))
                print(DefaultDownloadResponse)
            })
    }

DefaultDownloadResponse.destinationURL when Online downloaded

▿ destinationURL : Optional<URL>
    ▿ some : file:///Users/macuser/Library/Developer/CoreSimulator/Devices/4B6C2727-46AB-4797-8CBB-D5A897867013/data/Containers/Data/Application/08441079-027E-4A5C-A504-4151A8405CF0/Documents/660444321507407187.pdf
      - _url : file:///Users/macuser/Library/Developer/CoreSimulator/Devices/4B6C2727-46AB-4797-8CBB-D5A897867013/data/Containers/Data/Application/08441079-027E-4A5C-A504-4151A8405CF0/Documents/660444321507407187.pdf

when Offline its not downloaded or not picked from local

finished with error [-1009] Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo={_kCFStreamErrorCodeKey=50, NSUnderlyingError=0x600002fd50e0 {Error Domain=kCFErrorDomainCFNetwork Code=-1009 "(null)" UserInfo={_kCFStreamErrorCodeKey=50, _kCFStreamErrorDomainKey=1}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDownloadTask <98102CE1-D70F-4A0E-AB89-8CAAEFE29213>.<13>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
    "LocalDownloadTask <98102CE1-D70F-4A0E-AB89-8CAAEFE29213>.<13>"
), NSLocalizedDescription=The Internet connection appears to be offline., NSErrorFailingURLStringKey=http://pdfv2.zta.com/Pdf/GetPageFromPdfUrl?url=http://d4static.zed.com/31/2019/8585/6999605/6999605.pdf&page=1,

Solution

  • Here I am checking if file exists or not first.

    //Call it like this
    checkIfFileExists(urlString: "your_url")
    
    
    func checkIfFileExists(urlString: String) {
        let path                                 = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
        let url                                  = NSURL(fileURLWithPath: path)
        let fileName                             = urlString.fileName()
        let fileManager                          = FileManager.default
        let filePath                             = url.appendingPathComponent("\(fileName).pdf")?.path
        print("filePath : \(String(describing: filePath))")
        if fileManager.fileExists(atPath: filePath!) {
            print("File exists")
        } else {
            print("File doesn't exists")
            stackoverFlowTask()
        }
    }
    
    func stackoverFlowTask() {
        downloadFile(url: "your_url", filetype: ".pdf", callback: { success, response in
    
            if !success || response == nil {
                return false
            }
    
            return true
        })
    }
    
    
    public func downloadFile(url:String, filetype: String, callback:@escaping (_ success:Bool, _ result:Any?)->(Bool)) -> Void {
        var destination = DownloadRequest.suggestedDownloadDestination(for: .documentDirectory)
        if filetype.elementsEqual(".pdf"){
            destination = { _, _ in
                let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
                let downloadFileName = url.fileName()
                let fileURL = documentsURL.appendingPathComponent("\(downloadFileName).pdf")
                return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
            }
        }
    
        Alamofire.download(
            url,
            method: .get,
            parameters: nil,
            encoding: JSONEncoding.default,
            headers: nil,
            to: destination).downloadProgress(closure: { (progress) in
                //progress closure
                print(progress)
            }).response(completionHandler: { (DefaultDownloadResponse) in
                //here you able to access the DefaultDownloadResponse
                //result closure
                callback(DefaultDownloadResponse.response?.statusCode == 200, DefaultDownloadResponse.destinationURL?.absoluteString.replacingOccurrences(of: "file://", with: ""))
                print(DefaultDownloadResponse)
            })
    }
    

    Extension:

    extension String {
        func fileName() -> String {
            return self.replacingOccurrences(of: "[/+.:.-=.%&]", with: "", options: .regularExpression, range: nil)
        }
    }