如何在swift中下载文件?

时间:2021-08-25 16:30:41

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.

我刚开始学习来自android的苹果swift编程。我现在基本上可以阅读和操作swift代码了,还学习了一些在iOS swift编程中使用的常见类,但仍然对语法和所有东西感到困惑。

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

我在下载文件。比如说,从这个URL。

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

in a button click. Maybe with visual progress too

在点击一个按钮。也许还有视觉上的进步

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

通过在*的搜索,我偶然发现了Alamofire。我可能会尝试,但我不确定这是不是最好的方法。

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!

因此,我想问一下,在实现我的目标时,我的选择(iOS7和iOS8)是什么?而且,正反两方面都很棒!

9 个解决方案

#1


35  

Example downloader class without Alamofire:

示例downloader类没有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

斯威夫特3版本

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

还要注意的是,要在磁盘上下载大文件,而不是在内存中。看到“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()
    }
}

#2


17  

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

#3


13  

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.

只要应用程序在前台,Devran和djunod的解决方案就可以工作。如果在下载过程中切换到另一个应用程序,则会失败。我的文件大小在10mb左右,下载需要一些时间。所以我需要我的下载功能,即使应用进入后台。

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.

由于不支持completionhandler,因此不封装解决方案。很抱歉。

--Swift 2.3--

——迅速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--

以下是如何调用Swift 2.3

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

--Swift 3--

——迅速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--

以下是如何呼叫——Swift 3——

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

#4


10  

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

如果您只需要下载文本文件到字符串,您可以使用这个简单的方式,Swift 3:

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:

您应该知道,网络操作可能需要一些时间,为了防止它在主线程中运行并锁定您的UI,您可能希望异步执行代码,例如:

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

#5


2  

Here is the Swift 4 version:

以下是Swift的4版:

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

#6


1  

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

尝试这段代码,只有Swift 3.0首先创建nsobject文件,将此代码复制到创建的文件中。

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

#7


1  

Swift 3

斯威夫特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

这段代码100%工作

#8


0  

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

#9


-1  

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

使用URLSessionDownloadTask在后台下载文件,这样即使应用程序终止,它们也可以完成。

For more information see:

更多信息见:

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

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

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

它还展示了如何对并行运行的多个任务执行进度监控:

#1


35  

Example downloader class without Alamofire:

示例downloader类没有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

斯威夫特3版本

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

还要注意的是,要在磁盘上下载大文件,而不是在内存中。看到“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()
    }
}

#2


17  

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

#3


13  

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.

只要应用程序在前台,Devran和djunod的解决方案就可以工作。如果在下载过程中切换到另一个应用程序,则会失败。我的文件大小在10mb左右,下载需要一些时间。所以我需要我的下载功能,即使应用进入后台。

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.

由于不支持completionhandler,因此不封装解决方案。很抱歉。

--Swift 2.3--

——迅速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--

以下是如何调用Swift 2.3

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

--Swift 3--

——迅速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--

以下是如何呼叫——Swift 3——

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

#4


10  

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

如果您只需要下载文本文件到字符串,您可以使用这个简单的方式,Swift 3:

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:

您应该知道,网络操作可能需要一些时间,为了防止它在主线程中运行并锁定您的UI,您可能希望异步执行代码,例如:

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

#5


2  

Here is the Swift 4 version:

以下是Swift的4版:

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

#6


1  

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

尝试这段代码,只有Swift 3.0首先创建nsobject文件,将此代码复制到创建的文件中。

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

#7


1  

Swift 3

斯威夫特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

这段代码100%工作

#8


0  

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

#9


-1  

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

使用URLSessionDownloadTask在后台下载文件,这样即使应用程序终止,它们也可以完成。

For more information see:

更多信息见:

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

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

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

它还展示了如何对并行运行的多个任务执行进度监控: