Skip to main content

使用Swift实现iOS中的文件下载 – Part 1

FILE DOWNLOADING IN SWIFT – PART 1

如何通过URLSession来下载文件?这里我们通过URLSession来下载一个存储在服务器的文件,文件为zip格式存档。下载完成以后我们会通过ZIPFoundation这个第三方package来对文件进行解压操作。

通过URLSession来下载文件,我们需要用到URLSession中的downloadTask方法,同时为了异常处理和下载进度展示,我们还需要URLSessionDownloadDelegate委托。

在例子中我们使用的文件是一个储存在服务器的zip文件,支持Https下载。URL事先申明了一个变量URL_RESOURCE_BG,大家自己测试的时候可以使用任何可以直接下载的文件作为测试对象。

这里我们先做一个最简单下载测试。新建一个iOS工程,并且新建一个swift文件名为“FileEngine.swift”。我的会将所有下载和文件操作的相关方法(aka函数,抱歉,我从小到大一直以来习惯称之为“方法”,实际上是一回事)写在这个文件中。

首先我们从服务器下载一个zip文件,保存在app沙盒的tmp目录中,同时打印出文件的地址。

Swift
import Foundation

func fetchResourcePackage(url: URL, completion: @escaping (URL?, Error?) -> ()) {
    let task = URLSession.shared.downloadTask(with: url) { (location: URL?, response: URLResponse?, error: Error?) in
        guard let location = location, error == nil else {
            completion(nil, error)
            return
        }

        do {
            let tmpDirectory = FileManager.default.temporaryDirectory
            let targetURL = tmpDirectory.appendingPathComponent(url.lastPathComponent)
            try FileManager.default.moveItem(at: location, to: targetURL)
            completion(targetURL, nil)
        } catch {
            print("File error: \(error)")
            completion(nil, error)
        }
    }
    task.resume()
}

FileManager和过去Objective-C中完全一样,只有少量的语法上的变更。这个方法需要一个传入URL变量来处理下载的文件网址。最后除了打印到控制台外,没有包含异常处理,所以在真实应用中,我们需要尽可能完整的设计异常处理。

此外,这个例子使用的是共享的会话,对于少量的请求来说,这是可以的,但如果你要下载大量的文件,你可能会想要使用URLSessionConfiguration创建你自己的URLSession。

请记住,所有的UI更新都必须在主线程上进行。如果你打算根据下载进度或完成情况更新UI,请确保你在主队列上调度这些更新。此处我们先做一个简单的测试调用这个方法。

Swift
if let url = URL(string: "http://example.com/path/to/your/file.zip") {
    fetchResourcePackage(url: url) { (url, error) in
        if let error = error {
            print("Error: \(error)")
        } else if let url = url {
            print("Downloaded file's URL: \(url)")
        }
    }
}

如果URL正确,并且下载过程中没有遇到网络问题的话,这个方法执行以后会打印出文件在本地的URL。在使用虚拟机做调试的时候这是很有用的,我们可以在Finder中找到App沙盒的具体地址,并且对下载文件做具体的诊断。

接下来为了测试方便我们在SwiftUI中添加一个Download按钮,点击以后开始执行下载方法。

Swift
import SwiftUI

struct ContentView: View {
    var fileEngine = FileEngine()

    var body: some View {
        Button(action: {
            self.fileEngine.fetchResourcePackage() { (url, error) in
                if let error = error {
                    print("Error: \(error)")
                } else if let url = url {
                    print("Downloaded file's URL: \(url)")
                }
            }
        }) {
            Text("Download")
        }
    }
}

点击以后我们可以在console中获得下载下来的zip文件地址。

下一讲我们来实现下载进度在UI上面的呈现,将会用到URLSession的委托方法和Progress Bar组件的使用。

Happy coding!

Development, Downloading, iOS, Networking, Swift, Tutorial