1

I need to download a pdf from the storage and save it locally on an iOS device, so it can be seen in Files.

Here is the code is taken from the docs, which I'm using:

override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        let userID = Auth.auth().currentUser!.uid
        print(userID)

        // Get a reference to the storage service using the default Firebase App
        let storage = Storage.storage()

        // Create a storage reference from our storage service
        let storageRef = storage.reference()

        // Create a reference to the file you want to download
        let islandRef = storageRef.child("pdf/sample.pdf")

        // Create local filesystem URL
        let localURL = URL(string: "pdf/sample.pdf")!

        // Download to the local filesystem
        let downloadTask = islandRef.write(toFile: localURL) { url, error in
            if let error = error {
                // Uh-oh, an error occurred!
            } else {
                // Local file URL for "images/island.jpg" is returned
            }
        }

    }

When I try to run this ViewController, it doesn't crash but throws the following error:

"The file couldn’t be opened because the specified URL type isn’t supported." UserInfo={NSURL=pdf/sample.pdf}

The file in the Firebase Storage is saved in a folder called pdf/sample.pdf. Eventually, I wish to take the reference from the storage and pass it in a RealtimeDatabase, so the user can download it by viewing details about it in a table view.

Mayank Patel
  • 3,868
  • 10
  • 36
  • 59
MrPool
  • 370
  • 9
  • 27

2 Answers2

1

I think what need to do is to specify in which path to your local filesystem you want to save the downloaded document. So let say you want to use the temporary folder to save your pdf. You can try the following:

let tmporaryDirectoryURL = FileManager.default.temporaryDirectory
let localURL = tmporaryDirectoryURL.appendingPathComponent("sample.pdf")

islandRef.write(toFile: localURL) { url, error in
    if let error = error {
       print("\(error.localizedDescription)")
    } else {
       self.presentActivityViewController(withUrl: url)
    }
 }

Once the file is downloaded in order to save it in the Files app you will need to use UIActivityViewController.

func presentActivityViewController(withUrl url: URL) {
    DispatchQueue.main.async {
      let activityViewController = UIActivityViewController(activityItems: [url], applicationActivities: nil)
      activityViewController.popoverPresentationController?.sourceView = self.view
      self.present(activityViewController, animated: true, completion: nil)
    }
}

I haven't tested it but my assumption is that you get this error because your localURL variable is not a filesystem URL.

axel
  • 422
  • 2
  • 14
  • Getting the following error: `Cannot convert value of type 'URL' to expected argument type 'String'` – MrPool Apr 15 '19 at 11:03
  • Sorry. I updated my answer to use directly the url instead of re creating it again. – axel Apr 15 '19 at 11:05
  • Made the changes, no errors. But the download process isn't being initiated. – MrPool Apr 15 '19 at 11:13
  • Ok. I did one more edit. Add `downloadTask.resume()`. Are getting into the completion block? – axel Apr 15 '19 at 11:21
  • The completion block throws an error when it has to print the URL, here is the error `load failed with error Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLStringKey=https://firebasestorage.googleapis.com/v0/b/project-6a073.appspot.com/o/pdf%2Fsample.pdf?alt=media, NSErrorFailingURLKey=https://firebasestorage.googleapis.com/v0/b/nameoftheproject-6a073.appspot.com/o/pdf%2Fsample.pdf?alt=media, _NSURLErrorRelatedURLSessionTaskErrorKey=( "LocalDownloadTask .<2>" )` I've tried and shorten the error to add it here. – MrPool Apr 15 '19 at 11:40
  • The PDF file is present in the simulator data under `tmp`. It's not viewable on the device or its folders. – MrPool Apr 15 '19 at 11:58
  • Hmm. You mean even that the file is saved you also receive the error? – axel Apr 15 '19 at 12:00
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/191849/discussion-between-axel-and-mrpool). – axel Apr 15 '19 at 12:05
0

Instead of using URL(string: String) you should be using URL(fileURLWithPath: String) when opening files.

marosoaie
  • 2,352
  • 23
  • 32
  • Would I have to add anything else to initiate the download? – MrPool Apr 15 '19 at 10:29
  • Did you try it? I'm not familiar with the Firebase API, but the URL is certainly a problem. – marosoaie Apr 15 '19 at 10:31
  • Yes, I did. It doesn't log the error, but it does not initiate the download. Here is the changes I made `let localURL = URL(fileURLWithPath: "pdf/sample.pdf")` . – MrPool Apr 15 '19 at 10:35
  • @marosoaie is right but I think if still it does not work then may be you have to add `NSAppTransportSecurity` in .plist file. – Emon Apr 15 '19 at 10:37