swift 如何在Safari或WebView中打开本地PDF文件

4c8rllxm  于 12个月前  发布在  Swift
关注(0)|答案(5)|浏览(193)

我用的是Swift 5。这段代码没有做任何事情,但如果它是一个PDF,是在网络上,它打开Safari罚款。
我想使用本地保存的本地PDF文件。

print(file.absoluteString)
UIApplication.shared.open(URL(filePath: file.absoluteString))

文件路径在这里,我可以验证文件是否存在
模拟器和iPad

file:///Users/admin/Library/Developer/CoreSimulator/Devices/503B73CA-5121-40CC-AC5C-6713F47A60F7/data/Containers/Data/Application/05C1515A-26FF-4EC8-B748-03F661BF7B15/Documents/00A1.pdf

file:///var/mobile/Containers/Data/Application/2797F491-6E67-492E-B6C1-03DAEDDA5783/Documents/00A1.pdf

我认为这是一个URL模式问题,文件://不被接受(也许我们可以白名单不知何故?)

km0tfn4u

km0tfn4u1#

这是一个安全功能。您无法让Safari从iOS上的应用程序打开本地文件。您可以使用PDFView打开它,正如Alexey所建议的那样。但是,由于您的pdf文件不是应用程序包的一部分,但它位于Documents文件夹中,因此您需要以这种方式生成文件路径:

let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("00A1.pdf")

下面是完整的代码,包括下载部分:

import UIKit
import PDFKit

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let remote = URL(string:"https://www.tutorialspoint.com/swift/swift_tutorial.pdf")!
        let folder = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        let local = folder.appendingPathComponent("00A1.pdf")

        if FileManager.default.fileExists(atPath: local.path) {
            openPdf(at:local)
        } else {
            downloadFile(from:remote, to:local) { _ in
                DispatchQueue.main.async {
                    self.openPdf(at:local)
                }
            }
        }
    }
    
    func openPdf(at url: URL) {
        let pdfView = PDFView(frame: view.bounds)
        pdfView.document = PDFDocument(url: url)
        pdfView.displayMode = .singlePageContinuous
        pdfView.autoScales = true
        view.addSubview(pdfView)
    }
    
    func downloadFile(from remote: URL, to local:URL, completionHandler: @escaping ((Error?)->Void)) {
        let session = URLSession(configuration: URLSessionConfiguration.default)
        let task = session.downloadTask(with: URLRequest(url:remote)) { (temp, _, error) in
            var exception = error
            if let temp = temp, exception == nil {
                do {
                    try FileManager.default.moveItem(at: temp, to: local)
                } catch {
                    exception = error
                }
            }
            completionHandler(exception)
        }
        task.resume()
    }
}
gg0vcinb

gg0vcinb2#

尝试使用QLPreviewController,在单击文件或其他内容的位置添加此代码。

import QuickLook
import UIKit

func previewDocument(with url: URL) {
        let preview = QLPreviewController()
        preview.dataSource = self
        preview.navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
        previewItem = url as NSURL <- your file path in URL format
        self.present(preview, animated: true)
    }
brccelvz

brccelvz3#

根据我得到的答案,没有办法让Safari打开本地文件。
所以我唯一能完美工作的方法就是使用UIDocumentInteractionController类:

import UIKit

class DocumentController: NSObject, ObservableObject, UIDocumentInteractionControllerDelegate
{
    let controller = UIDocumentInteractionController()
    func presentDocument(url: URL)
    {
        controller.delegate = self
        controller.url = url
        controller.presentPreview(animated: true)
    }

    func documentInteractionControllerViewControllerForPreview(_: UIDocumentInteractionController) -> UIViewController
    {
       
        return (UIApplication
            .shared
            .connectedScenes
            .compactMap { ($0 as? UIWindowScene)?.keyWindow }
            .last?.rootViewController)!
    }
}

您的使用方式:

DocumentController().presentDocument(url: url)
ijnw1ujt

ijnw1ujt4#

使用关联的应用程序打开:

NSWorkspace.shared.open(someLocalUrl)   // macOS
UIApplication.shared.open(someLocalUrl) // iOS

用一些精确的应用程序打开:

// macOS
NSWorkspace.shared.open(someLocalUrl, withApplicationAt: appUrl, configuration: NSWorkspace.OpenConfiguration())

// iOS
UIApplication.shared.open( // similar to MacOS

附言:
URL对象必须有效。本地文件的有效URL必须使用

URL(fileURLWithPath: path)

更多关于URL的信息:https://stackoverflow.com/a/59464032/4423545

qfe3c7zg

qfe3c7zg5#

选项1:

func viewDidLoad() {
   super.viewDidLoad()

   let webView = WKWebView()
   webView.frame = view.bounds

   if let url = Bundle.main.url(forResource: "00A1", withExtension: "pdf") {
    webView.load(URLRequest(url: url))
   }

}

...还有一个使用PDFView的选项:

import UIKit
import PDFKit

class ViewController: UIViewController {

    private let pdfView: PDFView = {
        let view = PDFView()
        view.displayMode = .singlePageContinuous
        view.autoScales = true
        return view
    }()

    // MARK: - Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()
    
        pdfView.frame = view.bounds
    
        if let path = Bundle.main.path(forResource: "00A1", ofType: "pdf") {
            if let pdfDocument = PDFDocument(url: URL(fileURLWithPath: path)) {
                pdfView.document = pdfDocument
            }
        }
    }
}

相关问题