I have url with pdf extension. On tapping the url, I want to show user with options to open URL with apps (which should include safari browser as well). I might achieve this by first downloading file from url in document directory and then open the file. But I don't want to download the file, rather I want to give user options to open that url. This is what I have tried for first downloading and then opening the file but even this is not showing up the options to pick the apps :
func openDocument(document: Document)
{
let url = URL(string: document.documentUrl)
var urlData = Data()
do
{
urlData = try Data(contentsOf: url!)
}
catch
{
}
if urlData != nil {
var paths: [Any] = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let temp = NSURL.fileURL(withPath: NSTemporaryDirectory(), isDirectory: true)
// let temp = NSURL(
let targetPath = temp.appendingPathComponent("\("name").pdf")
do
{
//try urlData.write(to: URL(fileURLWithPath: targetPath), options: .atomic)
try urlData.write(to: targetPath, options: .atomic)
}
catch let error as NSError {
print("Could not write file", error.localizedDescription)
}
}
var paths: [Any] = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let temp = NSURL.fileURL(withPath: NSTemporaryDirectory(), isDirectory: true)
let targetPath = temp.appendingPathComponent("\("name").pdf")
let pdfUrl = URL(fileURLWithPath: targetPath.absoluteString)
if pdfUrl != nil {
documentInteractionController = UIDocumentInteractionController(url: pdfUrl)
documentInteractionController.name = document.documentName
documentInteractionController.delegate = self
documentInteractionController.presentPreview(animated: true)
}
}
Related
I try to save given video locally after then I need those saved videos for playing video in my app. I can't handle the saving video. Here is my saving try :
func saveVideoDocumentDirectory(url : URL){
let fileManager = FileManager.default
let paths = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent(".MOV")
do{
let videoData = try Data(contentsOf: url)
fileManager.createFile(atPath: paths as String, contents: videoData, attributes: nil)
}catch{
//
}
}
here is the get file try
func getVideo(){
let fileManager = FileManager.default
let videoPAth = (self.getDirectoryPath() as NSString).appendingPathComponent(".MOV")
if fileManager.fileExists(atPath: videoPAth){
print(videoPAth)
play(url: URL(string: videoPAth)!)
}else{
print("No Video")
}
}
here is my play video func :
func play(url : URL)
{
let player = AVPlayer(url: url)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
present(playerViewController, animated: true)
{
playerViewController.player!.play()
}
}
Instead of Filemanager.createFile(), try using write instead.
let videoData = try Data(contentsOf: url)
try videoData.write(to: paths, options: .atomic)
Also, I recommend creating a folder first (from this answer).
extension URL {
static func createFolder(folderName: String) -> URL? {
let fileManager = FileManager.default
// Get document directory for device, this should succeed
if let documentDirectory = fileManager.urls(for: .documentDirectory,
in: .userDomainMask).first {
// Construct a URL with desired folder name
let folderURL = documentDirectory.appendingPathComponent(folderName)
// If folder URL does not exist, create it
if !fileManager.fileExists(atPath: folderURL.path) {
do {
// Attempt to create folder
try fileManager.createDirectory(atPath: folderURL.path,
withIntermediateDirectories: true,
attributes: nil)
} catch {
// Creation failed. Print error & return nil
print(error.localizedDescription)
return nil
}
}
// Folder either exists, or was created. Return URL
return folderURL
}
// Will only be called if document directory not found
return nil
}
}
Then, you can save like this:
guard let folderURL = URL.createFolder(folderName: "StoredVideos") else {
print("Can't create url")
return
}
let permanentFileURL = folderURL.appendingPathComponent(nameOfYourFile).appendingPathExtension("MOV")
let videoData = try Data(contentsOf: url)
try videoData.write(to: permanentFileURL, options: .atomic)
This will save you the hassle of NSSearchPathForDirectoriesInDomains.
I am generating a PDF of a UIView and storing with a name in myforms the PFD is being generated and console prints PDF is Available but it shows nothing but a white screen in VC
here is what I am doing :
I have this code to generate a PDF
#IBAction func createAct(_ sender: Any) {
print("Creat PDF")
self.createPdfFromView(mainView: mainView, saveToDocumentsWithFileName: "myforms")
}
func createPdfFromView(mainView: UIView, saveToDocumentsWithFileName fileName: String)
{
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, mainView.bounds, nil)
UIGraphicsBeginPDFPage()
guard let pdfContext = UIGraphicsGetCurrentContext() else { return }
mainView.layer.render(in: pdfContext)
UIGraphicsEndPDFContext()
if let documentDirectories = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first {
let documentsFileName = documentDirectories + "/" + fileName
debugPrint(documentsFileName)
pdfData.write(toFile: documentsFileName, atomically: true)
}
}
then I have this in console :
Creat PDF
"/Users/jawaidahmed/Library/Developer/CoreSimulator/Devices/3F95BE09-0F25-427C-9ED9-4BDB16DC3600/data/Containers/Data/Application/1EC22FBC-79E7-4AC5-BB7D-13783CC34516/Documents/myforms"
and I am using this PDFViewController to retrieve the file in a webview
override func viewDidLoad() {
super.viewDidLoad()
let check = "myforms"
var pdfURL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)).last! as URL
print("check final = \(pdfURL)")
pdfURL = pdfURL.appendingPathComponent(check) as URL
if let pdfBundleURL = Bundle.main.url(forResource: "myforms", withExtension: nil, subdirectory: nil) {
do {
let data = try Data(contentsOf: pdfBundleURL)
//Lastly, write your file to the disk.
try data.write(to: pdfURL, options: .atomicWrite)
}
catch {
// catch errors here
}
}
do{
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let url = URL(fileURLWithPath: path)
var filePath = url.appendingPathComponent(check).path
let fileManager1 = FileManager.default
if fileManager1.fileExists(atPath: filePath) {
print("FILE AVAILABLE in VC")
filePath = "file://\(filePath)"
let fileUrlkk = Foundation.URL(string: filePath)
let data = try Data(contentsOf: fileUrlkk!)
self.webView.load(data, mimeType: filePath, textEncodingName:"utf-8", baseURL: pdfURL.deletingLastPathComponent())
} else {
print("FILE NOT AVAILABLE in VC")
}
}
catch let error as NSError {
print("An error took place: \(error)")
}
}
And I am receiving this in console :
FILE AVAILABLE in VC
It means file is generated and available but it shows only empty VC white background only
self.webView.load(data, mimeType: "application/pdf", textEncodingName:"utf-8", baseURL: pdfURL.deletingLastPathComponent())
replace textEncodingName:""
with
textEncodingName:"utf-8"
check it
Try this for loading in Webview.I tried with your sample..It works
let FileName = "myforms"
let Filemanager = NSFileManager.defaultManager()
let docURL = Filemanager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as NSURL
print(docURL)
let pdfPATH = docURL.URLByAppendingPathComponent(FileName)
print(pdfPATH)
let data = NSData(contentsOfURL: pdfPATH)
WBview.loadData(data!, MIMEType: "application/pdf", textEncodingName: "utf-8", baseURL: pdfPATH.URLByDeletingLastPathComponent!)
I have downloaded a pdf from remote server and saved it in document directory. Now I'm trying to retrieve it and display the pdf in the webView but I keep getting this exception:
failed to find PDF header: `%PDF' not found.
before this exception it showing this exception as well:
objc[8087]: Class PLBuildVersion is implemented in both /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/AssetsLibraryServices.framework/AssetsLibraryServices (0x11f29dcc0) and /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/PhotoLibraryServices.framework/PhotoLibraryServices (0x11f0b46f0).
One of the two will be used. Which one is undefined.
But I have noticed that when I try to run from mobile instead of emulator then this second exception is gone. Below is my code for fetching it:
let check:String = FileNames[0] + ".pdf"
print("check = \(check)")
// Method 1
let docURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let targetURL = docURL.appendingPathComponent(check)
var request = URLRequest(url: targetURL)
webView.loadRequest(request)
/*
// Method 2
var pdfURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! as URL
pdfURL = pdfURL.appendingPathComponent(check) as URL
print("check url = \(pdfURL)")
let data = try! Data(contentsOf: pdfURL)
print("check data = \(data)")
webView.load(data, mimeType: "application/pdf", textEncodingName:"utf-8", baseURL: pdfURL) // pdfURL.deletingLastPathComponent()
*/
//let requestk = NSURLRequest(url: pdfURL as URL)
// webView.loadRequest(requestk as URLRequest)
// Method 3
/* let fileManager = FileManager.default
let documentsUrl = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0] as NSURL
var pdf = documentsUrl.appendingPathComponent(check)
print("check item fetching from documentsUrl = \(pdf)")
let req = NSURLRequest(url: pdf!)
self.webView.loadRequest(req as URLRequest)
*/
I have searched a lot about this exception and followed all the possible solutions but none of it is working. But if I try to display this pdf directly from the remote server's address it is getting displayed. And also I have checked that this pdf is stored correctly. I have tried loading through both webView.loadRequest and webView.load with data method, maybe I'm missing something small.
Update
var pdfURL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)).last! as URL
print("check final = \(pdfURL)")
pdfURL = pdfURL.appendingPathComponent(check) as URL
do{
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let url = URL(fileURLWithPath: path)
var filePath = url.appendingPathComponent(check).path
let fileManager1 = FileManager.default
if fileManager1.fileExists(atPath: filePath) {
print("FILE AVAILABLE in VC")
// let fileUrlkk = NSURL(string: filePath)// converting string into URL
filePath = "file://\(filePath)"
let fileUrlkk = Foundation.URL(string: filePath)
let data = try Data(contentsOf: fileUrlkk!)
// let data = try Data(contentsOf: pdfURL) // tried but didn’t work
self.webView.load(data, mimeType: "application/pdf", textEncodingName:"", baseURL: pdfURL.deletingLastPathComponent())
} else {
print("FILE NOT AVAILABLE in VC")
}
}
catch let error as NSError {
print("An error took place: \(error)")
}
it displays "FILE AVAILABLE in VC" but still with this exception.
Use below code to load PDF in WebView
Swift 3.0
var pdfURL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)).last! as URL
pdfURL = pdfURL.appendingPathComponent("Swift.pdf") as URL
let data = try! Data(contentsOf: pdfURL)
self.webView.load(data, mimeType: "application/pdf", textEncodingName:"", baseURL: pdfURL.deletingLastPathComponent())
Where pdf file store in Document directory here is the path.
/Documents/Swift.pdf
----- UPDATE ------
Create new project.
Drag 1 sample PDF in bundle "sample.pdf"
And change your controller code with below
that's it run
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
let check = "Swift.pdf"
var pdfURL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)).last! as URL
print("check final = \(pdfURL)")
pdfURL = pdfURL.appendingPathComponent(check) as URL
if let pdfBundleURL = Bundle.main.url(forResource: "sample", withExtension: "pdf", subdirectory: nil, localization: nil) {
do {
let data = try Data(contentsOf: pdfBundleURL)
//Lastly, write your file to the disk.
try data.write(to: pdfURL, options: .atomicWrite)
}
catch {
// catch errors here
}
}
do{
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let url = URL(fileURLWithPath: path)
var filePath = url.appendingPathComponent(check).path
let fileManager1 = FileManager.default
if fileManager1.fileExists(atPath: filePath) {
print("FILE AVAILABLE in VC")
// let fileUrlkk = NSURL(string: filePath)// converting string into URL
filePath = "file://\(filePath)"
let fileUrlkk = Foundation.URL(string: filePath)
let data = try Data(contentsOf: fileUrlkk!)
// let data = try Data(contentsOf: pdfURL) // tried but didn’t work
self.webView.load(data, mimeType: "application/pdf", textEncodingName:"", baseURL: pdfURL.deletingLastPathComponent())
} else {
print("FILE NOT AVAILABLE in VC")
}
}
catch let error as NSError {
print("An error took place: \(error)")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
just use
do{
let directoryURL = try manager.url(for:.documentDirectory,in:.userDomainMask, appropriateFor:nil, create:true)
let docURL = NSURL(string:"XXX.pdf", relativeTo:directoryURL)
}
catch{print("ERROR")
}
I'm trying to download a file from a server, by sending the id of the file. I tried several things but the file is getting downloaded as CFNetworkDownload.tmp file.
I want it to save as the file that exists. The file type can be PNG,JPEG,PDF,DOCX,PPTX,XLSX. Tried many things but in vain. I'm sure it must be something simple i'm missing to understand here
Tried the below. Difference being in most of the examples, the file name is in the URL. But I send id and get file in response.
How to download file in swift?
How To Download Multiple Files Sequentially using NSURLSession downloadTask in Swift
Below is my code.
func downloadFile(id : String, fileName : String) -> Void {
let session = URLSession.shared
let url = URL(string: qaDownloadURL+id)!
var request = URLRequest(url: url)
request.httpMethod = "POST"
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("Success: \(statusCode)")
}
do {
// let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
//
// self.savePath = documentsUrl!.absoluteString + "/" + fileName
//
// let fileURL = URL(fileURLWithPath: self.savePath)
//
// let dataFromURL = NSData(contentsOf: tempLocalUrl)
// dataFromURL?.write(to: fileURL, atomically: true)
var documentsDirectory: String?
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
if paths.count > 0
{
documentsDirectory = paths.first!
}
self.savePath = documentsDirectory!// + "/" + fileName
let fileURL = URL(fileURLWithPath: self.savePath)
let dataFromURL = NSData(contentsOf: tempLocalUrl)
dataFromURL?.write(to: fileURL, atomically: true)
// try FileManager.default.copyItem(at: tempLocalUrl, to: fileURL)
DispatchQueue.main.async {
let documentController = UIDocumentInteractionController.init(url: fileURL)
documentController.delegate = self
documentController.presentPreview(animated: true)
}
} catch (let writeError) {
print("error writing file \(self.savePath) : \(writeError)")
}
} else {
print("Failure: %#", error?.localizedDescription);
}
}
task.resume()
}
You cannot write data into a location which represents a directory, you need to specify the full path including the file name.
Using modern URL related API you can replace the entire do block with
do {
let documentFolderURL = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let fileURL = documentFolderURL.appendingPathComponent(fileName)
try FileManager.default.copyItem(at: tempLocalUrl, to: fileURL)
DispatchQueue.main.async {
let documentController = UIDocumentInteractionController.init(url: fileURL)
documentController.delegate = self
documentController.presentPreview(animated: true)
}
}
or use URLSessionDataTask which returns the raw data rather than downloading the file to a temporary location and save the Data directly for example
let task = session.dataTask(with: request) { (data, response, error) in
guard error == nil else {
print(error!)
return
}
// Success
if let statusCode = (response as? HTTPURLResponse)?.statusCode {
print("Success: \(statusCode)")
}
do {
let documentFolderURL = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let fileURL = documentFolderURL.appendingPathComponent(fileName)
try data!.write(to: fileURL)
DispatchQueue.main.async {
let documentController = UIDocumentInteractionController.init(url: fileURL)
documentController.delegate = self
documentController.presentPreview(animated: true)
}
} catch {
print("error writing file \(fileName) : \(error)")
}
}
task.resume()
If this does not work the error is related to somewhere else.
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?
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)
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
}
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]);
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()
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.
if you want to print the PDF data wich is in the directoryURL then use :
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{
}
//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()
}
For Swift 5 and up Version: Save PDF base64 String Data to Document Directory
Create a Folder where you want to save PDF file with Name
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
}
}
}
Write PDF base64 String Data to Document Directory
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)
}
}