PDF文件阅读问题仅在离线模式下快速

Posted

技术标签:

【中文标题】PDF文件阅读问题仅在离线模式下快速【英文标题】:PDF File reading Issue only on Offline mode swift 【发布时间】:2020-01-13 11:18:04 【问题描述】:

我已经成功实现了pdf文件的下载机制。文件正在下载并保存到模拟器的文档目录中。 问题是当我尝试断开互联网连接时,本地存储的文件无法访问。在我的应用程序中,我有两种模式在线和离线。在在线模式下,我存储数据并在离线模式下访问。唯一的问题是使用 pdf 文件。

如何离线访问pdf文件?

viewController 代码:

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类:

@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 在线下载时

▿ 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

离线时未下载或未从本地选择

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,

【问题讨论】:

据我所知,建议将您的 pdf 移动到自定义目录并从那里读取,一切都将在离线时正常工作。我的意思是从.documentDirectory 移动到某个自定义目录。 @VadimNikolaev 我已经使用自定义目录更新了代码,但在没有互联网的情况下仍然相同,我什么也得不到。检查我更新的代码。 我没有看到文件移动。我的意思是像here 这样的逻辑 - 保存到 .documentDirectory ,然后转到自定义。我有同样的问题,它帮助了我 @VadimNikolaev 谢谢你让我实现它并回复你。 @VadimNikolaev 我已经实现了代码,根据您的参考链接,我的 pdf 已经下载到 documentDirectory。所以它必须是可访问的。我觉得(FileManager.default.fileExists(atPath: (response as! String).removingPercentEncoding!) 导致路径错误,因为响应一旦脱机就会为零。 【参考方案1】:

这里我先检查文件是否存在。

//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")
        ***Task()
    


func ***Task() 
    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 String 
    func fileName() -> String 
        return self.replacingOccurrences(of: "[/+.:.-=.%&]", with: "", options: .regularExpression, range: nil)
    

【讨论】:

完美完成,非常感谢您的努力,我非常感激。非常感谢。

以上是关于PDF文件阅读问题仅在离线模式下快速的主要内容,如果未能解决你的问题,请参考以下文章

怎样快速预览pdf文档

在离线模式下将 Jprofiler Controller 与 weblogic 进程一起使用

如何用PDF制作电子书

仅在离线时使用 ServiceWorker 缓存

pdf添加书签的快速方法

PDG格式文件转PDF