【问题标题】:Swift - Automatically save pdf file to Files app On My iPhoneSwift - 自动将 pdf 文件保存到我的 iPhone 上的文件应用程序
【发布时间】:2019-02-16 14:02:42
【问题描述】:

我急需帮助。

我正在尝试创建一个应用程序,该应用程序允许用户从链接保存 pdf 文件,例如我在 subjectLinks 数组中给出的示例,所有这些链接都指向一个 pdf 页面,我正在尝试下载它并保存在我的应用程序中。到目前为止,我已经到处搜索并找到了一种使用 Files 应用程序的方法,所以我在代码中所做的是下载 pdf 的数据并使用 UIDocument 和 presentPreview 打开它以显示它,我已经设法允许用户共享下载的文件并将其保存到文件中。

但是问题出现了,因为我想让它在用户单击下载时自动保存到目录中的文件应用程序中,这样用户就不需要单击选项按钮然后选择保存到文件和然后寻找保存它的位置。这可能吗??

如果这不可能,至少当用户选择选项按钮并单击保存到文件时,它会自动创建一个单独的目录,用户可以在其中查看并保存 pdf 文件?

I want to do this as most times, when Save to Files is chosen, saving 'On My iPhone' is not available as there is no directory or such present so it can only be saved to google drive or iCloud Drive and this是一个很大的不便。

抱歉,帖子太长了。但如果有人能帮助解决我的问题,我将不胜感激。非常感谢你:)

P.S 到目前为止,我的代码中的所有内容都运行良好,只是我完全不知道如何实现上面概述的功能?

import UIKit
import StoreKit

class TableViewController: UITableViewController {

let documentInteractionController = UIDocumentInteractionController()

let subjectLinks = ["https://pastpapers.papacambridge.com/Cambridge%20International%20Examinations%20(CIE)/AS%20and%20A%20Level/Accounting%20(9706)/2015%20Jun/9706_s15_qp_42.pdf", "https://pastpapers.papacambridge.com/Cambridge%20International%20Examinations%20(CIE)/AS%20and%20A%20Level/Economics%20(9708)/2017%20Jun/9708_s17_qp_12.pdf", "https://pastpapers.papacambridge.com/Cambridge%20International%20Examinations%20(CIE)/AS%20and%20A%20Level/Mathematics%20(9709)/2018-May-June/9709_s18_qp_12.pdf"]

override func viewDidLoad() {
    super.viewDidLoad()
    documentInteractionController.delegate = self as? UIDocumentInteractionControllerDelegate
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return subjectLinks.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
    cell.textLabel?.text = subjectLinks[indexPath.row]
    return cell
}

override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]?
{
    // 1
    let shareAction = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: "Download" , handler: { (action:UITableViewRowAction, indexPath: IndexPath) -> Void in
        // 2
        let downloadMenu = UIAlertController(title: nil, message: "Download this paper", preferredStyle: .actionSheet)

        let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil)

        downloadMenu.addAction(UIAlertAction(title: "Download", style: UIAlertActionStyle.destructive, handler: { action in self.storeAndShare(withURLString: self.subjectLinks[indexPath.row])}))
        downloadMenu.addAction(cancelAction)

        self.present(downloadMenu, animated: true, completion: nil)
    })
    // 3
    let rateAction = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: "Rate" , handler: { (action:UITableViewRowAction, indexPath:IndexPath) -> Void in
        // 4
        let rateMenu = UIAlertController(title: nil, message: "Rate this App", preferredStyle: .actionSheet)

        let appRateAction = UIAlertAction(title: "Rate", style: UIAlertActionStyle.default, handler: {action in SKStoreReviewController.requestReview()})
        let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil)

        rateMenu.addAction(appRateAction)
        rateMenu.addAction(cancelAction)

        self.present(rateMenu, animated: true, completion: nil)
    })
    // 5
    return [shareAction,rateAction]
}

}
    extension TableViewController {
    /// This function will set all the required properties, and then provide a preview for the document
    func share(url: URL) {
        documentInteractionController.url = url
        documentInteractionController.uti = url.typeIdentifier ?? "public.data, public.content"
        documentInteractionController.name = url.localizedName ?? url.lastPathComponent
        documentInteractionController.presentPreview(animated: true)
    }

    /// This function will store your document to some temporary URL and then provide sharing, copying, printing, saving options to the user
    func storeAndShare(withURLString: String) {
        guard let url = URL(string: withURLString) else { return }
        /// START YOUR ACTIVITY INDICATOR HERE
        URLSession.shared.dataTask(with: url) { data, response, error in
            guard let data = data, error == nil else { return }
            let fileManager = FileManager.default
            do {
                let documentDirectory = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create:false)
                let fileURL = documentDirectory.appendingPathComponent("fileName.pdf")
                try data.write(to: fileURL)

                DispatchQueue.main.async {
                    self.share(url: fileURL)
                }
            } catch {
                print(error)
            }
            }.resume()
    }
}
extension TableViewController: UIDocumentInteractionControllerDelegate {
    /// If presenting atop a navigation stack, provide the navigation controller in order to animate in a manner consistent with the rest of the platform
    func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
        guard let navVC = self.navigationController else {
            return self
        }
        return navVC
    }
}

【问题讨论】:

  • 未经用户同意保存文件?你吓到我了。
  • 哈哈哈@ElTomato 不用担心,它只会在用户点击下载并选择保存时保存,它只是自动保存到某个位置,而无需用户选择。跨度>

标签: swift pdf download nsfilemanager nsdocumentdirectory


【解决方案1】:

下载任何pdf文件并自动保存在iPhone文件夹中的示例。

    let urlString = "https://www.tutorialspoint.com/swift/swift_tutorial.pdf"
    let url = URL(string: urlString)
    let fileName = String((url!.lastPathComponent)) as NSString
    //Mark:  Create destination URL
    let documentsUrl:URL =  (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first as URL?)!
    let destinationFileUrl = documentsUrl.appendingPathComponent("\(fileName)")
    //Mark: Create URL to the source file you want to download
    let fileURL = URL(string: urlString)
    let sessionConfig = URLSessionConfiguration.default
    let session = URLSession(configuration: sessionConfig)
    let request = URLRequest(url:fileURL!)
    let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in
        if let tempLocalUrl = tempLocalUrl, error == nil {
            //Mark: Success
            if let statusCode = (response as? HTTPURLResponse)?.statusCode {
                print("Successfully downloaded. Status code: \(statusCode)")
            }
            do {
                try FileManager.default.copyItem(at: tempLocalUrl, to: destinationFileUrl)
                do {
                    //Mark: Show UIActivityViewController to save the downloaded file
                    let contents  = try FileManager.default.contentsOfDirectory(at: documentsUrl, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
                    for indexx in 0..<contents.count {
                        if contents[indexx].lastPathComponent == destinationFileUrl.lastPathComponent {
                            let activityViewController = UIActivityViewController(activityItems: [contents[indexx]], applicationActivities: nil)
                            self.present(activityViewController, animated: true, completion: nil)
                        }
                    }
                }
                catch (let err) {
                    print("error: \(err)")
                }
            } catch (let writeError) {
                print("Error creating a file \(destinationFileUrl) : \(writeError)")
            }
        } else {
            print("Error took place while downloading a file. Error description: \(error?.localizedDescription ?? "")")
        }
    }
    task.resume()
    
    

【讨论】:

    【解决方案2】:

    步骤#1:需要在info.plist中添加权限

        <key>UIFileSharingEnabled</key>
        <true/>
        <key>LSSupportsOpeningDocumentsInPlace</key>
        <true/>
    

    步骤 #2:从服务器 url[任何文档] 下载文档

    func downloadPdf(sender:UIButton) {
        DispatchQueue.main.async {
            //Do UI Code here.
            let pdfUrl = self.myOrderListModel?.myorderList?[sender.tag].invoiceUrl ?? ""
            guard let fileURL = URL(string: pdfUrl) else { return }
            var originalUrlStr : String = ""
            print(fileURL.pathExtension)
            if fileURL.pathExtension == ""{
                originalUrlStr = pdfUrl + ".pdf"
            } else {
                originalUrlStr = pdfUrl
            }
            guard let originalUrl = URL(string: originalUrlStr) else { return }
            let urlSession = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue())
            let downloadTask = urlSession.downloadTask(with: originalUrl)
            downloadTask.resume()
        }
    }
    
    extension InvoiceViewController:  URLSessionDownloadDelegate {
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
        print("File Downloaded Location- ",  location)
        guard let url = downloadTask.originalRequest?.url else {
            return
        }
        let docsPath = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
        let destinationPath = docsPath.appendingPathComponent(url.lastPathComponent)
        try? FileManager.default.removeItem(at: destinationPath)
        do{
            try FileManager.default.copyItem(at: location, to: destinationPath)
            print("File Downloaded Location- ",  destinationPath)
            DispatchQueue.main.async {
                let urlString: String = destinationPath.absoluteString
                self.saveInvoiceToDevice(filePath: urlString)
            }
        }catch let error {
            print("Copy Error: \(error.localizedDescription)")
        }
      }
    }
    

    步骤#3:将下载的文件保存在设备“文件”文件夹中

        func saveInvoiceToDevice(filePath : String) {
        let fileURL = URL(string: filePath)
        if FileManager.default.fileExists(atPath: fileURL!.path){
            let url = URL(fileURLWithPath: fileURL!.path)
            let activityViewController: UIActivityViewController = UIActivityViewController(activityItems: [url], applicationActivities: nil)
            activityViewController.popoverPresentationController?.sourceView=self.view
            //If user on iPad
            if UIDevice.current.userInterfaceIdiom == .pad {
                if activityViewController.responds(to: #selector(getter: UIViewController.popoverPresentationController)) {
                }
            }
            self.present(activityViewController, animated: true, completion: nil)
        }
        else {
            debugPrint("document was not found")
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-15
      • 2019-01-16
      • 2023-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-25
      • 1970-01-01
      相关资源
      最近更新 更多