How to download file in swift?

IosSwiftFileDownload

Ios Problem Overview


I just started learning apple swift programming for iOS coming from android. I basically can now read and manipulate swift code and also learned some common classes used in iOS swift programming but still having some confusion with the syntax and everything.

I'm trying to download file. Like, lets just say coming from this URL

var url = "http://www.mywebsite.com/myfile.pdf"

in a button click. Maybe with visual progress too

Through searching here in stackoverflow, I stumbled upon Alamofire. I might try it but I'm not sure if this is the best way for me to do it.

So, I would like to ask how and what are my options (iOS7 and iOS8) in achieving my goal. Also, pros and cons would be awesome!

Ios Solutions


Solution 1 - Ios

Example downloader class without Alamofire:

class Downloader {
    class func load(URL: NSURL) {
        let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration()
        let session = NSURLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)
        let request = NSMutableURLRequest(URL: URL)
        request.HTTPMethod = "GET"
        let task = session.dataTaskWithRequest(request, completionHandler: { (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
            if (error == nil) {
                // Success
                let statusCode = (response as NSHTTPURLResponse).statusCode
                println("Success: \(statusCode)")
                
                // This is your file-variable:
                // data
            }
            else {
                // Failure
                println("Failure: %@", error.localizedDescription);
            }
        })
        task.resume()
    }
}

This is how to use it in your own code:

class Foo {
    func bar() {
        if var URL = NSURL(string: "http://www.mywebsite.com/myfile.pdf") {
            Downloader.load(URL)
        }
    }
}

Swift 3 Version

Also note to download large files on disk instead instead in memory. see `downloadTask:

class Downloader {
    class func load(url: URL, to localUrl: URL, completion: @escaping () -> ()) {
        let sessionConfig = URLSessionConfiguration.default
        let session = URLSession(configuration: sessionConfig)
        let request = try! URLRequest(url: url, method: .get)

        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 {
                    try FileManager.default.copyItem(at: tempLocalUrl, to: localUrl)
                    completion()
                } catch (let writeError) {
                    print("error writing file \(localUrl) : \(writeError)")
                }

            } else {
                print("Failure: %@", error?.localizedDescription);
            }
        }
        task.resume()
    }
}

Solution 2 - Ios

Swift 4 and Swift 5 Version if Anyone still needs this

import Foundation

class FileDownloader {
    
    static func loadFileSync(url: URL, completion: @escaping (String?, Error?) -> Void)
    {
        let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        
        let destinationUrl = documentsUrl.appendingPathComponent(url.lastPathComponent)
        
        if FileManager().fileExists(atPath: destinationUrl.path)
        {
            print("File already exists [\(destinationUrl.path)]")
            completion(destinationUrl.path, nil)
        }
        else if let dataFromURL = NSData(contentsOf: url)
        {
            if dataFromURL.write(to: destinationUrl, atomically: true)
            {
                print("file saved [\(destinationUrl.path)]")
                completion(destinationUrl.path, nil)
            }
            else
            {
                print("error saving file")
                let error = NSError(domain:"Error saving file", code:1001, userInfo:nil)
                completion(destinationUrl.path, error)
            }
        }
        else
        {
            let error = NSError(domain:"Error downloading file", code:1002, userInfo:nil)
            completion(destinationUrl.path, error)
        }
    }
    
    static func loadFileAsync(url: URL, completion: @escaping (String?, Error?) -> Void)
    {
        let documentsUrl =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        
        let destinationUrl = documentsUrl.appendingPathComponent(url.lastPathComponent)
        
        if FileManager().fileExists(atPath: destinationUrl.path)
        {
            print("File already exists [\(destinationUrl.path)]")
            completion(destinationUrl.path, nil)
        }
        else
        {
            let session = URLSession(configuration: URLSessionConfiguration.default, delegate: nil, delegateQueue: nil)
            var request = URLRequest(url: url)
            request.httpMethod = "GET"
            let task = session.dataTask(with: request, completionHandler:
            {
                data, response, error in
                if error == nil
                {
                    if let response = response as? HTTPURLResponse
                    {
                        if response.statusCode == 200
                        {
                            if let data = data
                            {
                                if let _ = try? data.write(to: destinationUrl, options: Data.WritingOptions.atomic)
                                {
                                    completion(destinationUrl.path, error)
                                }
                                else
                                {
                                    completion(destinationUrl.path, error)
                                }
                            }
                            else
                            {
                                completion(destinationUrl.path, error)
                            }
                        }
                    }
                }
                else
                {
                    completion(destinationUrl.path, error)
                }
            })
            task.resume()
        }
    }
}

Here is how to call this method :-

let url = URL(string: "http://www.filedownloader.com/mydemofile.pdf")
FileDownloader.loadFileAsync(url: url!) { (path, error) in
    print("PDF File downloaded to : \(path!)")
}

Solution 3 - Ios

Here's an example that shows how to do sync & async.

import Foundation

class HttpDownloader {

    class func loadFileSync(url: NSURL, completion:(path:String, error:NSError!) -> Void) {
        let documentsUrl =  NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first as! NSURL
        let destinationUrl = documentsUrl.URLByAppendingPathComponent(url.lastPathComponent!)
        if NSFileManager().fileExistsAtPath(destinationUrl.path!) {
            println("file already exists [\(destinationUrl.path!)]")
            completion(path: destinationUrl.path!, error:nil)
        } else if let dataFromURL = NSData(contentsOfURL: url){
            if dataFromURL.writeToURL(destinationUrl, atomically: true) {
                println("file saved [\(destinationUrl.path!)]")
                completion(path: destinationUrl.path!, error:nil)
            } else {
                println("error saving file")
                let error = NSError(domain:"Error saving file", code:1001, userInfo:nil)
                completion(path: destinationUrl.path!, error:error)
            }
        } else {
            let error = NSError(domain:"Error downloading file", code:1002, userInfo:nil)
            completion(path: destinationUrl.path!, error:error)
        }
    }
    
    class func loadFileAsync(url: NSURL, completion:(path:String, error:NSError!) -> Void) {
        let documentsUrl =  NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first as! NSURL
        let destinationUrl = documentsUrl.URLByAppendingPathComponent(url.lastPathComponent!)
        if NSFileManager().fileExistsAtPath(destinationUrl.path!) {
            println("file already exists [\(destinationUrl.path!)]")
            completion(path: destinationUrl.path!, error:nil)
        } else {
            let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration()
            let session = NSURLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)
            let request = NSMutableURLRequest(URL: url)
            request.HTTPMethod = "GET"
            let task = session.dataTaskWithRequest(request, completionHandler: { (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
                if (error == nil) {
                    if let response = response as? NSHTTPURLResponse {
                        println("response=\(response)")
                        if response.statusCode == 200 {
                            if data.writeToURL(destinationUrl, atomically: true) {
                                println("file saved [\(destinationUrl.path!)]")
                                completion(path: destinationUrl.path!, error:error)
                            } else {
                                println("error saving file")
                                let error = NSError(domain:"Error saving file", code:1001, userInfo:nil)
                                completion(path: destinationUrl.path!, error:error)
                            }
                        }
                    }
                }
                else {
                    println("Failure: \(error.localizedDescription)");
                    completion(path: destinationUrl.path!, error:error)
                }
            })
            task.resume()
        }
    }
}

Here's how to use it in your code:

let url = NSURL(string: "http://www.mywebsite.com/myfile.pdf") 
HttpDownloader.loadFileAsync(url, completion:{(path:String, error:NSError!) in
                println("pdf downloaded to: \(path)")
            })

Solution 4 - Ios

If you need to download only text file into String you can use this simple way, Swift 5:

let list = try? String(contentsOf: URL(string: "https://example.com/file.txt")!)

In case you want non optional result or error handling:

do {
    let list = try String(contentsOf: URL(string: "https://example.com/file.txt")!)
}
catch {
    // Handle error here
}

You should know that network operations may take some time, to prevent it from running in main thread and locking your UI, you may want to execute the code asynchronously, for example:

DispatchQueue.global().async {
    let list = try? String(contentsOf: URL(string: "https://example.com/file.txt")!)
}

Solution 5 - Ios

Devran's and djunod's solutions are working as long as your application is in the foreground. If you switch to another application during the download, it fails. My file sizes are around 10 MB and it takes sometime to download. So I need my download function works even when the app goes into background.

Please note that I switched ON the "Background Modes / Background Fetch" at "Capabilities".

Since completionhandler was not supported the solution is not encapsulated. Sorry about that.

--Swift 2.3--

import Foundation 
class Downloader : NSObject, NSURLSessionDownloadDelegate
{
    var url : NSURL? 
    // will be used to do whatever is needed once download is complete
    var yourOwnObject : NSObject?
    
    init(yourOwnObject : NSObject)
    {
        self.yourOwnObject = yourOwnObject
    }
    
    //is called once the download is complete
    func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL)
    {
        //copy downloaded data to your documents directory with same names as source file
        let documentsUrl =  NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first
        let destinationUrl = documentsUrl!.URLByAppendingPathComponent(url!.lastPathComponent!)
        let dataFromURL = NSData(contentsOfURL: location)
        dataFromURL?.writeToURL(destinationUrl, atomically: true)
        
        //now it is time to do what is needed to be done after the download
        yourOwnObject!.callWhatIsNeeded()
    }
    
    //this is to track progress
    func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64)
    {
    }
    
    // if there is an error during download this will be called
    func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?)
    {
        if(error != nil)
        {
            //handle the error
            print("Download completed with error: \(error!.localizedDescription)");
        }
    }
    
    //method to be called to download
    func download(url: NSURL)
    {
        self.url = url
        
        //download identifier can be customized. I used the "ulr.absoluteString"
        let sessionConfig = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(url.absoluteString)
        let session = NSURLSession(configuration: sessionConfig, delegate: self, delegateQueue: nil)
        let task = session.downloadTaskWithURL(url)
        task.resume()
    }
}

And here is how to call in --Swift 2.3--

    let url = NSURL(string: "http://company.com/file.txt")
    Downloader(yourOwnObject).download(url!)

--Swift 3--

class Downloader : NSObject, URLSessionDownloadDelegate {

var url : URL?
// will be used to do whatever is needed once download is complete
var yourOwnObject : NSObject?

init(_ yourOwnObject : NSObject)
{
    self.yourOwnObject = yourOwnObject
}

//is called once the download is complete
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)
{
    //copy downloaded data to your documents directory with same names as source file
    let documentsUrl =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
    let destinationUrl = documentsUrl!.appendingPathComponent(url!.lastPathComponent)
    let dataFromURL = NSData(contentsOf: location)
    dataFromURL?.write(to: destinationUrl, atomically: true)
    
    //now it is time to do what is needed to be done after the download
    yourOwnObject!.callWhatIsNeeded()
}

//this is to track progress
private func URLSession(session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64)
{
}

// if there is an error during download this will be called
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
{
    if(error != nil)
    {
        //handle the error
        print("Download completed with error: \(error!.localizedDescription)");
    }
}

//method to be called to download
func download(url: URL)
{
    self.url = url
    
    //download identifier can be customized. I used the "ulr.absoluteString"
    let sessionConfig = URLSessionConfiguration.background(withIdentifier: url.absoluteString)
    let session = Foundation.URLSession(configuration: sessionConfig, delegate: self, delegateQueue: nil)
    let task = session.downloadTask(with: url)
    task.resume()
}}

And here is how to call in --Swift 3--

    let url = URL(string: "http://company.com/file.txt")
    Downloader(yourOwnObject).download(url!)

Solution 6 - Ios

Here is the Swift 4 version:

static func loadFileAsync(url: URL, completion: @escaping (String?, Error?) -> Void)
{
    let documentsUrl =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
    
    let destinationUrl = documentsUrl.appendingPathComponent(url.lastPathComponent)
    
    if FileManager().fileExists(atPath: destinationUrl.path)
    {
        completion(destinationUrl.path, nil)
    }
    else
    {
        let session = URLSession(configuration: URLSessionConfiguration.default, delegate: nil, delegateQueue: nil)
        var request = URLRequest(url: url)
        request.httpMethod = "GET"
        let task = session.dataTask(with: request, completionHandler:
        {
            data, response, error in
            if error == nil
            {
                if let response = response as? HTTPURLResponse
                {
                    if response.statusCode == 200
                    {
                        if let data = data
                        {
                            if let _ = try? data.write(to: destinationUrl, options: Data.WritingOptions.atomic)
                            {
                                completion(destinationUrl.path, error)
                            }
                            else
                            {
                                completion(destinationUrl.path, error)
                            }
                        }
                        else
                        {
                            completion(destinationUrl.path, error)
                        }
                    }
                }
            }
            else
            {
                completion(destinationUrl.path, error)
            }
        })
        task.resume()
    }
}

Solution 7 - Ios

Swift 3

you want to download file bite by bite and show in progress view so you want to try this code

import UIKit

class ViewController: UIViewController,URLSessionDownloadDelegate,UIDocumentInteractionControllerDelegate {
    
    @IBOutlet weak var img: UIImageView!
    @IBOutlet weak var btndown: UIButton!
    var urlLink: URL!
    var defaultSession: URLSession!
    var downloadTask: URLSessionDownloadTask!
    //var backgroundSession: URLSession!
    @IBOutlet weak var progress: UIProgressView!
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Do any additional setup after loading the view, typically from a nib.
        
        let backgroundSessionConfiguration = URLSessionConfiguration.background(withIdentifier: "backgroundSession")
        defaultSession = Foundation.URLSession(configuration: backgroundSessionConfiguration, delegate: self, delegateQueue: OperationQueue.main)
        progress.setProgress(0.0, animated: false)
    }
    
    func startDownloading () {
        let url = URL(string: "http://publications.gbdirect.co.uk/c_book/thecbook.pdf")!
        downloadTask = defaultSession.downloadTask(with: url)
        downloadTask.resume()
    }
    
    @IBAction func btndown(_ sender: UIButton) {
 
        startDownloading()
        
    }
    
    func showFileWithPath(path: String){
        let isFileFound:Bool? = FileManager.default.fileExists(atPath: path)
        if isFileFound == true{
            let viewer = UIDocumentInteractionController(url: URL(fileURLWithPath: path))
            viewer.delegate = self
            viewer.presentPreview(animated: true)
        }
        
    }

    
    // MARK:- URLSessionDownloadDelegate
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
        
        print(downloadTask)
        print("File download succesfully")
        
        let path = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
        let documentDirectoryPath:String = path[0]
        let fileManager = FileManager()
        let destinationURLForFile = URL(fileURLWithPath: documentDirectoryPath.appendingFormat("/file.pdf"))
        
        if fileManager.fileExists(atPath: destinationURLForFile.path){
            showFileWithPath(path: destinationURLForFile.path)
            print(destinationURLForFile.path)
        }
        else{
            do {
                try fileManager.moveItem(at: location, to: destinationURLForFile)
                // show file
                showFileWithPath(path: destinationURLForFile.path)
            }catch{
                print("An error occurred while moving file to destination url")
            }
        }
        
        
        
    }
    
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
        progress.setProgress(Float(totalBytesWritten)/Float(totalBytesExpectedToWrite), animated: true)
    }
    
    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
        downloadTask = nil
        progress.setProgress(0.0, animated: true)
        if (error != nil) {
            print("didCompleteWithError \(error?.localizedDescription ?? "no value")")
        }
        else {
            print("The task finished successfully")
        }
    }
    
    func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController
    {
        return self
    }
        
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

use of this code you want to download file store automatically in Document Directory in your application

this code 100% Working

Solution 8 - Ios

Yes you can very easily downloads Files from the remote Url Using this code. This Code is working Fine for Me.

func DownlondFromUrl(){
   // Create destination URL 
let documentsUrl:URL =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first as URL!
let destinationFileUrl = documentsUrl.appendingPathComponent("downloadedFile.jpg")

//Create URL to the source file you want to download
let fileURL = URL(string: "https://s3.amazonaws.com/learn-swift/IMG_0001.JPG")

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

Solution 9 - Ios

Downloading a file in Swift 5 with progress reporting, encapsulated into a copy-paste friendly protocol-accessed class:

protocol FileDownloadingDelegate: class {
    func updateDownloadProgressWith(progress: Float)
    func downloadFinished(localFilePath: URL)
    func downloadFailed(withError error: Error)
}

class FilesDownloader: NSObject, URLSessionDownloadDelegate {
    private weak var delegate: FileDownloadingDelegate?

    func download(from url: URL, delegate: FileDownloadingDelegate) {
        self.delegate = delegate
        let sessionConfig = URLSessionConfiguration.background(withIdentifier: url.absoluteString) // use this identifier to resume download after app restart
        let session = Foundation.URLSession(configuration: sessionConfig, delegate: self, delegateQueue: nil)
        let task = session.downloadTask(with: url)
        task.resume()
    }

    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
        DispatchQueue.main.async { self.delegate?.downloadFinished(localFilePath: location) }
    }

    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
        DispatchQueue.main.async { self.delegate?.updateDownloadProgressWith(progress: Float(totalBytesWritten)/Float(totalBytesExpectedToWrite)) }
    }

    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
        guard let theError = error else { assertionFailure("something weird happened here"); return }
        DispatchQueue.main.async { self.delegate?.downloadFailed(withError: theError) }
    }

}

How to use it:

class MyViewController: UIViewController {

    private lazy var downloader = FilesDownloader()

    func downloadFile(from url: URL) {
        downloader.download(from: url, delegate: self)
    }

}

extension MyViewController: FileDownloadingDelegate {
    func updateDownloadProgressWith(progress: Float) {
        // self.downloadProgressView.setProgress(progress, animated: true)
    }

    func downloadFinished(tempFilePath: URL) {
        print("downloaded to \(tempFilePath)")
        // resave the file into your desired place using 
        // let dataFromURL = NSData(contentsOf: location)
        // dataFromURL?.write(to: yourDesiredFileUrl, atomically: true)
    }

    func downloadFailed(withError error: Error) {
        // handle the error
    }
}

Solution 10 - Ios

iOS 13 Swift 5, 5.1

@IBAction func btnDownload(_ sender: Any) {
    
    // file location to save download file
    let destination: DownloadRequest.DownloadFileDestination = { _, _ in
        var documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        documentsURL.appendPathComponent(statementPDF)
        return (documentsURL, [.removePreviousFile])
    }
    
    // Alamofire to download file
    Alamofire.download("http://pdf_url", to: destination).responseData { response in
        hideLoader()
        switch response.result {
        case .success:
            // write something here
            if response.destinationURL != nil {
                showAlertMessage(titleStr: APPNAME, messageStr: "File Saved in Documents!")
                
            }
        case .failure:
            showAlertMessage(titleStr: APPNAME, messageStr: response.result.error.debugDescription)
        }
    }
}

Please add these permissions to info.plist, so you will able to check the download file in Document Directory

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

Solution 11 - Ios

After trying a few of the above suggestions without success (Swift versions...) I ended up using the official documentation: https://developer.apple.com/documentation/foundation/url_loading_system/downloading_files_from_websites

let downloadTask = URLSession.shared.downloadTask(with: url) {
    urlOrNil, responseOrNil, errorOrNil in
    // check for and handle errors:
    // * errorOrNil should be nil
    // * responseOrNil should be an HTTPURLResponse with statusCode in 200..<299
    
    guard let fileURL = urlOrNil else { return }
    do {
        let documentsURL = try
            FileManager.default.url(for: .documentDirectory,
                                    in: .userDomainMask,
                                    appropriateFor: nil,
                                    create: false)
        let savedURL = documentsURL.appendingPathComponent(fileURL.lastPathComponent)
        try FileManager.default.moveItem(at: fileURL, to: savedURL)
    } catch {
        print ("file error: \(error)")
    }
}
downloadTask.resume()

Solution 12 - Ios

Try This Code only Swift 3.0 First Create NS Object File Copy this code in created File

import UIKit

class Downloader : NSObject, URLSessionDownloadDelegate {
    
    var url : URL?
    // will be used to do whatever is needed once download is complete
    var obj1 : NSObject?
    
    init(_ obj1 : NSObject)
    {
        self.obj1 = obj1
    }
    
    //is called once the download is complete
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)
    {
        //copy downloaded data to your documents directory with same names as source file
        let documentsUrl =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
        let destinationUrl = documentsUrl!.appendingPathComponent(url!.lastPathComponent)
        let dataFromURL = NSData(contentsOf: location)
        dataFromURL?.write(to: destinationUrl, atomically: true)
        
        //now it is time to do what is needed to be done after the download
        //obj1!.callWhatIsNeeded()
    }
    
    //this is to track progress
    private func URLSession(session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64)
    {
    }
    
    // if there is an error during download this will be called
    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
    {
        if(error != nil)
        {
            //handle the error
            print("Download completed with error: \(error!.localizedDescription)");
        }
    }
    
    //method to be called to download
    func download(url: URL)
    {
        self.url = url
        
        //download identifier can be customized. I used the "ulr.absoluteString"
        let sessionConfig = URLSessionConfiguration.background(withIdentifier: url.absoluteString)
        let session = Foundation.URLSession(configuration: sessionConfig, delegate: self, delegateQueue: nil)
        let task = session.downloadTask(with: url)
        task.resume()
    }}

then Copy Below Code And put code in place of you want to download file

 object = "http://www.mywebsite.com/myfile.pdf"
       let url1 = URL(string: object!)
        Downloader(url1! as NSObject).download(url: url1!)

Solution 13 - Ios

Swift 3

class ViewController: UIViewController {
    var urlLink: URL!
    var defaultSession: URLSession!
    var downloadTask: URLSessionDownloadTask!
}

// MARK: Button Pressed
    @IBAction func btnDownloadPressed(_ sender: UIButton) {
        let urlLink1 = URL.init(string: "https://github.com/VivekVithlani/QRCodeReader/archive/master.zip")
        startDownloading(url: urlLink!)
}
    @IBAction func btnResumePressed(_ sender: UIButton) {
    downloadTask.resume()
}

@IBAction func btnStopPressed(_ sender: UIButton) {
    downloadTask.cancel()
}

@IBAction func btnPausePressed(_ sender: UIButton) {
    downloadTask.suspend()
}

    func startDownloading (url:URL) {
        let backgroundSessionConfiguration = URLSessionConfiguration.background(withIdentifier: "backgroundSession")
        defaultSession = Foundation.URLSession(configuration: backgroundSessionConfiguration, delegate: self, delegateQueue: OperationQueue.main)
        downloadProgress.setProgress(0.0, animated: false)
        downloadTask = defaultSession.downloadTask(with: urlLink)
        downloadTask.resume()
    }

// MARK:- URLSessionDownloadDelegate
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
    print("File download succesfully")
}

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
    downloadProgress.setProgress(Float(totalBytesWritten)/Float(totalBytesExpectedToWrite), animated: true)
}

func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
    downloadTask = nil
    downloadProgress.setProgress(0.0, animated: true)
    if (error != nil) {
        print("didCompleteWithError \(error?.localizedDescription)")
    }
    else {
        print("The task finished successfully")
    }
}

Solution 14 - Ios

You can also use a third party library that makes life easy, like Just

Just.get("http://www.mywebsite.com/myfile.pdf")

More awesome Swift stuff here https://github.com/matteocrippa/awesome-swift

Solution 15 - Ios

Background session (URLSessionDownloadTask, URLSessionUploadTask) is a part of background transfer approach which allows you to download/upload/cache files in background mode even if app was terminated. In this case when task is done iOS wakes up it (in background) and allows make some competition block in a limited time frame. It works because the downloading task is executed on nsurlsessiond daemon process[About]

[Background tasks]

Solution 16 - Ios

Use URLSessionDownloadTask to download files in background so that they can completed even if the app is terminated.

For more information see:

https://www.ralfebert.de/snippets/ios/urlsession-background-downloads/

It also shows how to implement progress monitoring for multiple tasks running in parallel:

Solution 17 - Ios

A simple, robust and elegant download manager supporting simultaneous downloads with closure syntax for progress and completion tracking. Written in Swift with Here

> And Use like it

func downloadGIF(url: String) {
    let filename = url
    let range: Range<String.Index> = filename.range(of:"media/")!
    let lastrange: Range<String.Index> = filename.range(of:"/200w_d")!
    let finalPath = String(filename[range.lowerBound..<lastrange.lowerBound])
    filename[range.lowerBound..<lastrange.lowerBound]
    let replaceFirstWords = finalPath.replace(string: "media/", replacement: "SocialStatus_GIF_")
    let destinationUrl = "\(replaceFirstWords).gif"
    
    let request = URLRequest(url: URL(string: imageData.bg_image)!)
    viewProgress.isHidden = false
    self.btnDownload.isHidden = true
    setSharingButtonFalse()
    let downloadKey = self.downloadManager.downloadFile(withRequest: request,
                                                        withName: destinationUrl,
                                                        shouldDownloadInBackground: true,
                                                        onProgress:  { [weak self] (progress) in
                                                            self?.viewProgress.progress = CGFloat(progress)
                                                            let val = progress * 100
                                                            print("val 1 == \(val)")
                                                            DispatchQueue.main.async {
                                                                self?.viewProgress.setProgressText("\(Int(val))")
                                                            }
                                                            
    }) { [weak self] (error, url) in
        if let error = error {
            print("Error = \(error as NSError)")
            self!.isDownloaded = false
            self!.viewProgress.isHidden = true
            self!.setSharingButtonTrue()
            self?.viewProgress.setProgressText("\(0)")
            print("handle error since couldn't save GIF")
        } else {
            if let url = url {
                self!.isDownloaded = true
                self!.saveGIFDownloaded()
                self!.viewProgress.isHidden = true
                self!.setSharingButtonTrue()
                self!.createAlbum()
                self!.saveGIF(url: url.absoluteURL)
             
            }
        }
    }
    
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionr_19View Question on Stackoverflow
Solution 1 - IosDevran Cosmo UenalView Answer on Stackoverflow
Solution 2 - IosMantuView Answer on Stackoverflow
Solution 3 - IosdjunodView Answer on Stackoverflow
Solution 4 - IosDmitriyView Answer on Stackoverflow
Solution 5 - IosAhmet AkkökView Answer on Stackoverflow
Solution 6 - IosinexcitusView Answer on Stackoverflow
Solution 7 - IosAmul4608View Answer on Stackoverflow
Solution 8 - IosAyush DixitView Answer on Stackoverflow
Solution 9 - IosVitaliiView Answer on Stackoverflow
Solution 10 - IosSandeep MauryaView Answer on Stackoverflow
Solution 11 - IosTomTascheView Answer on Stackoverflow
Solution 12 - IosAmul4608View Answer on Stackoverflow
Solution 13 - IosVivekView Answer on Stackoverflow
Solution 14 - IosbachrView Answer on Stackoverflow
Solution 15 - IosyoAlex5View Answer on Stackoverflow
Solution 16 - IosAzShView Answer on Stackoverflow
Solution 17 - IosParesh MangukiyaView Answer on Stackoverflow