草庐IT

ios - WKWebView 将 pdf 保存到 ibooks,从链接保存 pdf

coder 2023-09-16 原文

我是 Junior,目前正在 WKWebView 中的项目中工作,并且有打开 pdf 的链接。我可以在 Safari 中打开它,然后在 iBooks 中打开,但我希望它在我的应用程序中进行。可能吗 ?

下面是图片:

我可以选择pdf的图片

想象一下它会打开什么

我的 WebView 类

class WebVC: UIViewController, WKUIDelegate {



var webView: WKWebView!

override func viewDidLoad() {
    super.viewDidLoad()
    let myURL = NSURL(string: "\(savedURL!)")
    let myRequest = URLRequest(url: myURL! as URL)
    webView.load(myRequest)
    webView.allowsBackForwardNavigationGestures = true
    webView.allowsLinkPreview = false
}

override func viewWillAppear(_ animated: Bool) {
    self.navigationController?.toolbar.isHidden = false
}

override func loadView() {
    let webConfiguration = WKWebViewConfiguration()
    webView = WKWebView(frame: CGRect(x: 100, y: 100, width: 110, height: 110), configuration: webConfiguration)
    webView.uiDelegate = self
    view = webView

}

@IBAction func logoutPressed(_ sender: AnyObject) {
    defaults.set(false, forKey: "isLogged")
    defaults.set("EMPTY URL", forKey: "savedURL")
    _ = self.navigationController?.popToRootViewController(animated: true)
}


@IBAction func goBack(_ sender: Any?) {
    if (self.webView.canGoBack) {
        self.webView.goBack()
    }
}

}

最佳答案

  • 在webview中打开pdf

    //第一步

    webview.uiDelegate = self
    

    //第 2 步 - 实现委托(delegate)函数(这个函数可以让你在 webview 中打开任何点击的 pdf)

    func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
    
         // open in current view
         webView.load(navigationAction.request)
         // don't return a new view to build a popup into (the default behavior).
         return nil;
     }
    
  • 下载

在我的例子中,一旦我在 webview 中打开了 pdf,我就有了下载按钮,我用它来下载当前打开的 pdf

//第三步 - 委托(delegate)函数

    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        decisionHandler(WKNavigationActionPolicy.allow)
    }
    //find the mimeTime of the current url opened in webview, If it's pdf, we'll give option to download 
    func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
        
        if let mimeType = navigationResponse.response.mimeType {
            //check if mime exists in our acceptable mimes list
            if self.isMimeTypeConfigured(mimeType) {
                self.mime = mimeType
                self.currentUrl = navigationResponse.response.url
                addDownloadButton()
            }
        }
        decisionHandler(.allow)
    }

//第 4 步 - 创建带有辅助函数的扩展

//=== PDF downloading ===
struct MimeType {
    var type:String
    var fileExtension:String
}
extension DownloadManual {
    //button
    private func addDownloadButton(){
        let btn = UIBarButtonItem(image: UIImage(systemName: "tray.and.arrow.down.fill"), style: .plain, target: nil, action: #selector(downloadTapped))
        self.navigationItem.rightBarButtonItem = btn
    }
    @objc func downloadTapped(){
        self.showActivityIndicator(show: true)
        if let url = currentUrl {
            print("download from: \(url)")
            let filename = getDefaultFileName(forMimeType: self.mime)
            
            downloadData(fromURL: url, fileName: filename) { success, destinationURL in
                if success, let destinationURL = destinationURL {
                    
                    self.showActivityIndicator(show: false)
                    print("download result: \(success), \(destinationURL)")
                    self.fileDownloadedAtURL(url: destinationURL)
                }
            }
        }
    }
    
    //helper funcs
    private func isMimeTypeConfigured(_ mimeType:String) -> Bool {
        for record in self.mimeTypes {
            if mimeType.contains(record.type) {
                return true
            }
        }
        return false
    }
    
    func fileDownloadedAtURL(url: URL) {
        print("downloaded at: \(url)")
        DispatchQueue.main.async {
            let activityVC = UIActivityViewController(activityItems: [url], applicationActivities: nil)
            activityVC.popoverPresentationController?.sourceView = self.view
            activityVC.popoverPresentationController?.sourceRect = self.view.frame
            activityVC.popoverPresentationController?.barButtonItem = self.navigationItem.rightBarButtonItem
            self.present(activityVC, animated: true, completion: nil)
        }
    }
    private func downloadData(fromURL url:URL,
                              fileName:String,
                              completion:@escaping (Bool, URL?) -> Void) {
        webview.configuration.websiteDataStore.httpCookieStore.getAllCookies() { cookies in
            let session = URLSession.shared
            print("downloading ....")
            session.configuration.httpCookieStorage?.setCookies(cookies, for: url, mainDocumentURL: nil)
            let task = session.downloadTask(with: url) { localURL, urlResponse, error in
                if let localURL = localURL {
                    let destinationURL = self.moveDownloadedFile(url: localURL, fileName: fileName)
                    completion(true, destinationURL)
                }
                else {
                    completion(false, nil)
                }
            }

            task.resume()
        }
    }
    private func getDefaultFileName(forMimeType mimeType:String) -> String {
        for record in self.mimeTypes {
            if mimeType.contains(record.type) {
                return "default." + record.fileExtension
            }
        }
        return "default"
    }
    
    private func moveDownloadedFile(url:URL, fileName:String) -> URL {
        let tempDir = NSTemporaryDirectory()
        let destinationPath = tempDir + fileName
        let destinationURL = URL(fileURLWithPath: destinationPath)
        try? FileManager.default.removeItem(at: destinationURL)
        try? FileManager.default.moveItem(at: url, to: destinationURL)
        return destinationURL
    }

希望这对某人有帮助:)

关于ios - WKWebView 将 pdf 保存到 ibooks,从链接保存 pdf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40491077/

有关ios - WKWebView 将 pdf 保存到 ibooks,从链接保存 pdf的更多相关文章

  1. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  2. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  3. ruby-on-rails - Ruby url 到 html 链接转换 - 2

    我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.

  4. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  5. ruby-on-rails - Prawn PDF : I need to generate nested tables - 2

    我需要一个表,其中行实际上是2行表,一个嵌套表是..我怎样才能在Prawn中做到这一点?也许我需要延期..但哪一个? 最佳答案 现在支持子表:Prawn::Document.generate("subtable.pdf")do|pdf|subtable=pdf.make_table([["sub"],["table"]])pdf.table([[subtable,"original"]])end 关于ruby-on-rails-PrawnPDF:Ineedtogeneratenested

  6. ruby-on-rails - Prawn - 表格单元格内的链接 - 2

    我正在尝试用Prawn生成PDF。在我的PDF模板中,我有带单元格的表格。在其中一个单元格中,我有一个电子邮件地址:cell_email=pdf.make_cell(:content=>booking.user_email,:border_width=>0)我想让电子邮件链接到“mailto”链接。我知道我可以这样链接:pdf.formatted_text([{:text=>booking.user_email,:link=>"mailto:#{booking.user_email}"}])但是将这两行组合起来(将格式化文本作为内容)不起作用:cell_email=pdf.make_c

  7. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  8. ruby-on-rails - 有没有一种工具可以在编码时自动保存对文件的增量更改? - 2

    我最喜欢的Google文档功能之一是它会在我工作时不断自动保存我的文档版本。这意味着即使我在进行关键更改之前忘记在某个点进行保存,也很有可能会自动创建一个保存点。至少,我可以将文档恢复到错误更改之前的状态,并从该点继续工作。对于在MacOS(或UNIX)上运行的Ruby编码器,是否有具有等效功能的工具?例如,一个工具会每隔几分钟自动将Gitcheckin我的本地存储库以获取我正在处理的文件。也许我有点偏执,但这点小保险可以让我在日常工作中安心。 最佳答案 虚拟机有些人可能讨厌我对此的回应,但我在编码时经常使用VIM,它具有自动保存功

  9. ruby - 为什么不能使用类IO的实例方法noecho? - 2

    print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上

  10. ruby-on-rails - Rails 3.2 防止使用错误保存对象 - 2

    我有一个ActiveRecord对象,我想在不对模型进行永久验证的情况下阻止它被保存。您过去可以使用errors.add执行类似的操作,但它看起来不再有效了。user=User.lastuser.errors.add:name,"namedoesn'trhymewithorange"user.valid?#=>trueuser.save#=>true或user=User.lastuser.errors.add:base,"myuniqueerror"user.valid?#=>trueuser.save#=>true如何在不修改用户对象模型的情况下防止将用户对象保存在Rails3.2中

随机推荐