【问题标题】:Saving PDF Files with Swift in iOS and display them在 iOS 中使用 Swift 保存 PDF 文件并显示它们
【发布时间】:2015-06-11 08:30:49
【问题描述】:

我想构建一个应用程序,该应用程序还包括在应用程序内显示和保存 PDF 并在表格视图中显示它们(作为文件系统)并在我点击一个 PDF 时打开它们。

这是我的重要问题:

1.如何在我的应用程序上保存 PDF 本地(例如,如果用户可以输入一个 url)以及它将保存在哪里?

2。保存后,如何在 tableview 中显示所有本地存储的文件以打开它们?

【问题讨论】:

  • 看看下面的答案,你就有了解决方案;)

标签: ios swift pdf pdfkit


【解决方案1】:

对于 Swift 5 及更高版本:将 PDF base64 字符串数据保存到文档目录

创建一个文件夹,用于保存带有名称的 PDF 文件

   fileprivate func getFilePath() -> URL? {
            let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
            let directoryURl = documentDirectoryURL.appendingPathComponent("Invoice", isDirectory: true)
            
            if FileManager.default.fileExists(atPath: directoryURl.path) {
                return directoryURl
            } else {
                do {
                    try FileManager.default.createDirectory(at: directoryURl, withIntermediateDirectories: true, attributes: nil)
                    return directoryURl
                } catch {
                    print(error.localizedDescription)
                    return nil
                }
            }
        }

将 PDF base64 字符串数据写入文档目录

fileprivate func saveInvoice(invoiceName: String, invoiceData: String) {
    
    guard let directoryURl = getFilePath() else {
        print("Invoice save error")
        return }
    
    let fileURL = directoryURl.appendingPathComponent("\(invoiceName).pdf")
    
    guard let data = Data(base64Encoded: invoiceData, options: .ignoreUnknownCharacters) else {
        print("Invoice downloaded Error")
        self.hideHUD()
        return
    }
    
    do {
        try data.write(to: fileURL, options: .atomic)
        print("Invoice downloaded successfully")
    } catch {
        print(error.localizedDescription)
    }
}

【讨论】:

    【解决方案2】:
            //savePdf(urlString:url, fileName:fileName)
            let urlString = "here String with your URL"
            let url = URL(string: urlString)
            let fileName = String((url!.lastPathComponent)) as NSString
            // Create destination URL
            let documentsUrl:URL =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first as URL!
            let destinationFileUrl = documentsUrl.appendingPathComponent("\(fileName)")
            //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 {
                    // Success
                    if let statusCode = (response as? HTTPURLResponse)?.statusCode {
                        print("Successfully downloaded. Status code: \(statusCode)")
                    }
                    do {
                        try FileManager.default.copyItem(at: tempLocalUrl, to: destinationFileUrl)
                        do {
                            //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()
        }
    

    【讨论】:

    • 通过这个解决方案我可以在一个tableview中显示所有的本地存储文件吗?
    • 只会尝试保存,如果文件已经存在会报错
    【解决方案3】:

    如果你想将文件存储在Filesapp add`

    NSURL *url = [NSURL URLWithString:@"PATH TO PDF"];
    UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithURL:url inMode:UIDocumentPickerModeExportToService];
    [documentPicker setDelegate:self];
    [self presentViewController:documentPicker animated:YES completion:nil];
    

    这里是委托方法

    - (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller {
    }
    
    - (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls {
    
    }
    

    它将打开一个 DocumentPickerViewController,您可以在其中选择一个文件夹来存储文件。

    需要 iOS11 或更高版本。

    【讨论】:

      【解决方案4】:

      使用 Swift 在 Webview 中下载和显示 PDF。

      let request = URLRequest(url:  URL(string: "http://<your pdf url>")!)
              let config = URLSessionConfiguration.default
              let session =  URLSession(configuration: config)
              let task = session.dataTask(with: request, completionHandler: {(data, response, error) in
                  if error == nil{
                      if let pdfData = data {
                         let pathURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("\(filename).pdf")
                          do {
                              try pdfData.write(to: pathURL, options: .atomic)
                          }catch{
                              print("Error while writting")
                          }
      
                          DispatchQueue.main.async {
                              self.webView.delegate = self
                              self.webView.scalesPageToFit = true
                              self.webView.loadRequest(URLRequest(url: pathURL))
                          }
                      }
                  }else{
                      print(error?.localizedDescription ?? "")
                  }
              }); task.resume()
      

      【讨论】:

      • 很抱歉,请务必添加一些解释。
      • 那解释在哪里?
      • 什么是“文件名”
      • @BIJUC PDF 在 iPhone 中保存在哪里?
      【解决方案5】:

      斯威夫特 4.1

       func savePdf(urlString:String, fileName:String) {
              DispatchQueue.main.async {
                  let url = URL(string: urlString)
                  let pdfData = try? Data.init(contentsOf: url!)
                  let resourceDocPath = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)).last! as URL
                  let pdfNameFromUrl = "YourAppName-\(fileName).pdf"
                  let actualPath = resourceDocPath.appendingPathComponent(pdfNameFromUrl)
                  do {
                      try pdfData?.write(to: actualPath, options: .atomic)
                      print("pdf successfully saved!")
                  } catch {
                      print("Pdf could not be saved")
                  }
              }
          }
      
          func showSavedPdf(url:String, fileName:String) {
              if #available(iOS 10.0, *) {
                  do {
                      let docURL = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
                      let contents = try FileManager.default.contentsOfDirectory(at: docURL, includingPropertiesForKeys: [.fileResourceTypeKey], options: .skipsHiddenFiles)
                      for url in contents {
                          if url.description.contains("\(fileName).pdf") {
                             // its your file! do what you want with it!
      
                      }
                  }
              } catch {
                  print("could not locate pdf file !!!!!!!")
              }
          }
      }
      
      // check to avoid saving a file multiple times
      func pdfFileAlreadySaved(url:String, fileName:String)-> Bool {
          var status = false
          if #available(iOS 10.0, *) {
              do {
                  let docURL = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
                  let contents = try FileManager.default.contentsOfDirectory(at: docURL, includingPropertiesForKeys: [.fileResourceTypeKey], options: .skipsHiddenFiles)
                  for url in contents {
                      if url.description.contains("YourAppName-\(fileName).pdf") {
                          status = true
                      }
                  }
              } catch {
                  print("could not locate pdf file !!!!!!!")
              }
          }
          return status
      }
      

      【讨论】:

      • 我发现这个解决方案是最好的。
      • 最佳解决方案!
      【解决方案6】:

      如果您想打印位于 directoryURL 中的 PDF 数据,请使用:

      let printInfo = NSPrintInfo.shared
              let manager = FileManager.default
              do{
                  let directoryURL = try manager.url(for: .documentDirectory, in:.userDomainMask, appropriateFor:nil, create:true)
                  let docURL = NSURL(string:"LadetagMahlzeiten.pdf", relativeTo:directoryURL)
      
                  let pdfDoc =  PDFDocument.init(url: docURL! as URL)
      
                  let page = CGRect(x: 0, y: 0, width: 595.2, height: 1841.8) // A4, 72 dpi
      
                  let pdfView : PDFView = PDFView.init(frame: page)
      
                  pdfView.document = pdfDoc
      
                  let operation: NSPrintOperation = NSPrintOperation(view: pdfView, printInfo: printInfo)
                  operation.printPanel.options.insert(NSPrintPanel.Options.showsPaperSize)
                  operation.printPanel.options.insert(NSPrintPanel.Options.showsOrientation)
      
                  operation.run()
              }catch{
      
              }
      

      【讨论】:

        【解决方案7】:

        由于有几个人要求这个,这里相当于 Swift 中的第一个答案:

        //The URL to Save
        let yourURL = NSURL(string: "http://somewebsite.com/somefile.pdf")
        //Create a URL request
        let urlRequest = NSURLRequest(URL: yourURL!)
        //get the data
        let theData = NSURLConnection.sendSynchronousRequest(urlRequest, returningResponse: nil, error: nil)
        
        //Get the local docs directory and append your local filename.
        var docURL = (NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)).last as? NSURL
        
        docURL = docURL?.URLByAppendingPathComponent( "myFileName.pdf")
        
        //Lastly, write your file to the disk.
        theData?.writeToURL(docURL!, atomically: true)
        

        此外,由于此代码使用同步网络请求,我强烈建议将其分派到后台队列:

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
            //The URL to Save
            let yourURL = NSURL(string: "http://somewebsite.com/somefile.pdf")
            //Create a URL request
            let urlRequest = NSURLRequest(URL: yourURL!)
            //get the data
            let theData = NSURLConnection.sendSynchronousRequest(urlRequest, returningResponse: nil, error: nil)
        
            //Get the local docs directory and append your local filename.
            var docURL = (NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)).last as? NSURL
        
            docURL = docURL?.URLByAppendingPathComponent( "myFileName.pdf")
        
            //Lastly, write your file to the disk.
            theData?.writeToURL(docURL!, atomically: true)
        })
        

        以及 Swift 中第二个问题的答案:

        //Getting a list of the docs directory
        let docURL = (NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).last) as? NSURL
        
        //put the contents in an array.
        var contents = (NSFileManager.defaultManager().contentsOfDirectoryAtURL(docURL!, includingPropertiesForKeys: nil, options: NSDirectoryEnumerationOptions.SkipsHiddenFiles, error: nil))
        //print the file listing to the console
        println(contents)
        

        【讨论】:

        • 嗨!我测试了你的代码,它可以工作。我可以在控制台中看到文件的路径。但是,在设备中,我在路径中看到的 Documents 文件夹在哪里?如果我想下载文件然后显示它怎么办?谢谢
        • 您好!我很高兴它对你有用。就绝对路径而言,我不知道应用程序特定的 Documents 目录在 iPhone 上的位置。由于 Apple 故意混淆了开发人员的文件系统,因此您可以使用上面使用的各种常量来访问特定的 Documents 目录
        • 感谢您的回答!因此,如果我理解的话,我无法通过从目录或其他东西访问它来在 iPhone 中看到它。而已?还有一个问题:如果我想获取最新下载的pdf的内容(路径)怎么办?你能看看我的问题吗? stackoverflow.com/questions/40567952/… 非常感谢!
        【解决方案8】:

        我给出了一个在 iOS 中存储和检索 pdf 文档的示例。我希望这就是你要找的。

        1.如何在我的应用程序上保存 PDF 本地(例如,如果用户可以输入一个 url)以及它将保存在哪里?

        // the URL to save
        NSURL *yourURL = [NSURL URLWithString:@"http://yourdomain.com/yourfile.pdf"];
        // turn it into a request and use NSData to load its content
        NSURLRequest *request = [NSURLRequest requestWithURL:result.link];
        NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
        
        // find Documents directory and append your local filename
        NSURL *documentsURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
        documentsURL = [documentsURL URLByAppendingPathComponent:@"localFile.pdf"];
        
        // and finally save the file
        [data writeToURL:documentsURL atomically:YES];
        

        2。保存后,如何在 tableview 中显示所有本地存储的文件以打开它们?

        您可以检查文件是否已下载,也可以像这样列出 Documents 目录:

        // list contents of Documents Directory just to check
        NSURL *documentsURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
        
        NSArray *contents = [[NSFileManager defaultManager]contentsOfDirectoryAtURL:documentsURL includingPropertiesForKeys:nil options:NSDirectoryEnumerationSkipsHiddenFiles error:nil];
        
        NSLog(@"%@", [contents description]);
        

        【讨论】:

        • 感谢您的快速回复!我理解并会尽快将其翻译成 swift,或者您是否知道如何使用 Swift 来翻译?
        • 我试过了,但我做不到。我仍然有一些关于使用哪些数据类型的问题。
        • 你能把swift代码放在这里吗,它会很有帮助,提前谢谢:)
        • @MkaysWork 你能输入快速代码吗?非常感谢:)
        猜你喜欢
        • 2015-03-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-28
        • 1970-01-01
        相关资源
        最近更新 更多