返回 导航

Swift

hangge.com

Swift - HTTP网络操作库Alamofire使用详解3(文件下载,断点续传)

作者:hangge | 2015-12-09 08:54
相关文章系列:(文章代码均已升级至Swift3)
Swift - HTTP网络操作库Alamofire使用详解1(配置,以及数据请求)
Swift - HTTP网络操作库Alamofire使用详解2(文件上传)
[当前文章] Swift - HTTP网络操作库Alamofire使用详解3(文件下载,断点续传)
Swift - HTTP网络操作库Alamofire使用详解4(用户权限认证)


七,使用Alamofire进行文件下载

1,自定义下载文件的保存目录
下面代码将logo图片下载下来保存到用户文档目录下(Documnets目录),文件名不变。
//指定下载路径(文件名不变)
let destination: DownloadRequest.DownloadFileDestination = { _, response in
    let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let fileURL = documentsURL.appendingPathComponent(response.suggestedFilename!)
    //两个参数表示如果有同名文件则会覆盖,如果路径中文件夹不存在则会自动创建
    return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
}

//开始下载
Alamofire.download("http://www.hangge.com/blog/images/logo.png", to: destination)
    .response { response in
        print(response)
        
        if let imagePath = response.destinationURL?.path {
            let image = UIImage(contentsOfFile: imagePath)
        }
    }
}
将logo图片下载下来保存到用户文档目录下的file1子目录(Documnets/file1目录),文件名改成myLogo.png。
//指定下载路径和保存文件名
let destination: DownloadRequest.DownloadFileDestination = { _, _ in
    let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let fileURL = documentsURL.appendingPathComponent("file1/myLogo.png")
    //两个参数表示如果有同名文件则会覆盖,如果路径中文件夹不存在则会自动创建
    return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
}

//开始下载
Alamofire.download("http://www.hangge.com/blog/images/logo.png", to: destination)
    .response { response in
        print(response)
        
        if let imagePath = response.destinationURL?.path {
            let image = UIImage(contentsOfFile: imagePath)
        }
    }
}

2,使用默认提供的下载路径
Alamofire内置的许多常用的下载路径方便我们使用,简化代码。注意的是,使用这种方式如果下载路径下有同名文件,不会覆盖原来的文件。
比如,下载到用户文档目录下可以改成:
let destination = DownloadRequest.suggestedDownloadDestination(for: .documentDirectory)
Alamofire.download("http://www.hangge.com/blog/images/logo.png", to: destination)

3,下载时附带请求参数

如果下载文件时需要传递一些参数,我们可以将参数拼接在 url 后面。也可以配置在 download 方法里的 parameters 参数中(其实这个方式最终也是拼接到 url 后面)。
//下面这两种方式效果是一样的
Alamofire.download("http://www.hangge.com/blog/images/logo.png?foo=bar", to: destination)
Alamofire.download("http://www.hangge.com/blog/images/logo.png", parameters: ["foo": "bar"],
                   to: destination)

4,下载进度
(1)下面代码在文件下载过程中会不断地打印下载进度,同时下载完成后也会打印完成信息。
Alamofire.download("http://www.hangge.com/favicon.ico", to: destination)
    .downloadProgress { progress in
        print("当前进度: \(progress.fractionCompleted)")
    }
    .responseData { response in
        if let data = response.result.value {
            print("下载完毕!")
            let image = UIImage(data: data)
        }
    }
(2)下载的过程中我们也可以得到已下载部分的大小,以及文件总大小。(单位都是字节)
Alamofire.download("http://www.hangge.com/favicon.ico", to: destination)
    .downloadProgress { progress in
        print("已下载:\(progress.completedUnitCount/1024)KB")
        print("总大小:\(progress.totalUnitCount/1024)KB")
    }
    .responseData { response in
        if let data = response.result.value {
            print("下载完毕!")
            let image = UIImage(data: data)
        }
}

5,断点续传(Resume Data) 
当下载过程中被意外停止时,可以在响应方法中把已下载的部分保存起来,下次再从断点继续下载。
下面通过样例演示如何断点续传:
(1)程序启动后自动开始下载文件
(2)点击“停止下载”,终止下载并把已下载的数据保存起来,进度条停止走动。
(3)点击“继续下载”,从上次终止的地方继续下载,进度条继续走动。
   
import UIKit
import Alamofire

class ViewController: UIViewController {
    
    //停止下载按钮
    @IBOutlet weak var stopBtn: UIButton!
    //继续下载按钮
    @IBOutlet weak var continueBtn: UIButton!
    //下载进度条
    @IBOutlet weak var progress: UIProgressView!
    
    //下载文件的保存路径(
    var destination:DownloadRequest.DownloadFileDestination!
    //用于停止下载时,保存已下载的部分
    var cancelledData: Data?
    
    //下载请求对象
    var downloadRequest: DownloadRequest!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //设置下载路径。保存到用户文档目录,文件名不变,如果有同名文件则会覆盖
         self.destination = { _, response in
            let documentsURL = FileManager.default.urls(for: .documentDirectory,
                                                        in: .userDomainMask)[0]
            let fileURL = documentsURL.appendingPathComponent(response.suggestedFilename!)
            //两个参数表示如果有同名文件则会覆盖,如果路径中文件夹不存在则会自动创建
            return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
        }
        
        //页面加载完毕就自动开始下载
        self.downloadRequest =  Alamofire.download(
            "http://dldir1.qq.com/qqfile/qq/QQ7.9/16621/QQ7.9.exe", to: destination)
        self.downloadRequest.downloadProgress(queue: DispatchQueue.main,
                                              closure: downloadProgress) //下载进度
        self.downloadRequest.responseData(completionHandler: downloadResponse) //下载停止响应
    }
    
    //下载过程中改变进度条
    
    func downloadProgress(progress: Progress) {
        //进度条更新
        self.progress.setProgress(Float(progress.fractionCompleted), animated:true)
        print("当前进度:\(progress.fractionCompleted*100)%")
    }
    
    
    //下载停止响应(不管成功或者失败)
    func downloadResponse(response: DownloadResponse<Data>) {
        switch response.result {
        case .success(let data):
            //self.image = UIImage(data: data)
            print("文件下载完毕: \(response)")
        case .failure:
            self.cancelledData = response.resumeData //意外终止的话,把已下载的数据储存起来
        }
    }
    
    //停止按钮点击
    @IBAction func stopBtnClick(_ sender: AnyObject) {
        self.downloadRequest?.cancel()
        self.stopBtn.isEnabled = false
        self.continueBtn.isEnabled = true
    }
    
    //继续按钮点击
    @IBAction func continueBtnClick(_ sender: AnyObject) {
        if let cancelledData = self.cancelledData {
            self.downloadRequest = Alamofire.download(resumingWith: cancelledData,
                                                      to: destination)
            self.downloadRequest.downloadProgress(queue: DispatchQueue.main,
                                                  closure: downloadProgress) //下载进度
            self.downloadRequest.responseData(completionHandler: downloadResponse) //下载停止响应
            self.stopBtn.isEnabled = true
            self.continueBtn.isEnabled = false
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}
源码下载:
hangge_972.zip(2015-12-06)
hangge_972.zip(2016-09-23 Swift3最新版)
评论

全部评论(16)

回到顶部