Saving PDF Files with Swift in iOS and display them

76,623

Solution 1

Since several people requested this, here is the equivalent to the first answer in 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)

Also, since this code uses a synchronous network request, I highly recommend dispatching it to a background queue:

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)
})

And the answer to second question in 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)



Solution 2

Swift 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
}

Solution 3

I am giving an example of storing and retrieving a pdf document in iOS. I hope that is what you are looking for.

1. How do I save a PDF local on my app ( for example if the user can enter a url) and where exactly will it save it ?

// 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. When saved, how can I show all the local storaged files within a tableview to open them?

You can check that the file has downloaded, or you can list the Documents directory like so:

// 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]);

Solution 4

If you want to store file in Files app 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];

And here are delegate methods

- (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller {
}

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

}

It will open a DocumentPickerViewController where you can choose a folder to store the file.

Requires iOS11 or later.

Solution 5

Downloading and displaying PDF in Webview using Swift.

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()
Share:
76,623
MkaysWork
Author by

MkaysWork

Updated on March 04, 2021

Comments

  • MkaysWork
    MkaysWork about 3 years

    I want to build an app which also includes the possibility to show and save PDFs inside the app and display them (as a FileSystem) within a tableview and open them when I tap on one PDF.

    Here are my important questions for that:

    1. How do I save a PDF local on my app ( for example if the user can enter a url) and where exactly will it save it ?

    2. When saved, how can I show all the local storaged files within a tableview to open them?

  • MkaysWork
    MkaysWork about 9 years
    Thanks for the quick reply! I understand and will try to translate it to swift as soon as I can, or do you even know how to make it with Swift?
  • MkaysWork
    MkaysWork about 9 years
    I tried it but I couldn't do it. I still have some problems of which datatypes to use.
  • Josip Bogdan
    Josip Bogdan almost 9 years
    can u put swift code here, it would be so helpfull, thanks in advance :)
  • vinbhai4u
    vinbhai4u almost 9 years
    @MkaysWork can you put the swift code please? Thanks a lot :)
  • Ne AS
    Ne AS over 7 years
    Hi! I tested your code and it works. I can see the path of the file in the console. But where is ,in the device, the Documents folder that I see in the path? What if I want to download the file and then display it? Thanks
  • Satre
    Satre over 7 years
    Hello! I'm glad it worked for you. In terms of absolute paths, I don't know where the app specific Documents directory is on the iPhone. Since Apple intentionally obfuscates the filesystem from developers, you can use the various constants used above to access the specific Documents directory
  • Ne AS
    Ne AS over 7 years
    Thanks for the answer! So if I understood, I can't see it in the iPhone by accessing to it from a directory or something else. That's it? And another question please: what if I want to take the cotent (the path) of the latest downloaded pdf? Can you please take a look in my issue please? stackoverflow.com/questions/40567952/… thanks a lot!
  • BIJU C
    BIJU C about 5 years
    Sorry for that, definitely add some explanation.
  • Nico Haase
    Nico Haase about 5 years
    And where is that explanation?
  • jbiser361
    jbiser361 over 4 years
    what is "fileName"
  • Muju
    Muju about 4 years
    @BIJUC Where the PDF is save in iPhone?
  • Michael Nelles
    Michael Nelles about 4 years
    With this solution can I show all the local storage files within a tableview?
  • Bruno Camargos
    Bruno Camargos about 4 years
    It will only try to save, if the file already exists will throw an error
  • Anees
    Anees almost 4 years
    I found this solution as the best.
  • iMinion
    iMinion over 3 years
    Best solution !
  • Moumen Alisawe
    Moumen Alisawe about 2 years
    You are a lifesaver