Swift用URLSession实现文件的下载

最近根据URLSession 实现文件的下载,简单地封装了一下注释很详细,这里不再过多的赘述,喜欢的可以看看.

  • 1 FileTool.swift 实现获取文件的大小/移动文件/文件是否存在等等的判断
  • 2 DownLoader.swift 是下载文件的主类
  • 3在Controller中创建DownLoader对象,即可使用

🙄

首先是 下载的类 DownLoader.swift

import UIKit

private let kCachePath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.cachesDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first
private let kTempPath = NSTemporaryDirectory()

class DownLoader: NSObject  {

    fileprivate var downLoadedPath : String?
    fileprivate var downLoadingPath : String?
    fileprivate var outputStream : OutputStream?
    fileprivate var tmpSize : CLongLong = 0
    fileprivate var totalSize : CLongLong = 0
    
    
    fileprivate lazy var session : URLSession  = {
        
        let config = URLSessionConfiguration.default
        let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)
        return session
        
    }()
    
    func downLoader(url : NSURL) {
        
        let fileName = url.lastPathComponent

        guard url.lastPathComponent != nil else {
            print("url有问题")
            return
        }
        
        self.downLoadingPath = kTempPath + "/" + fileName!
        self.downLoadedPath = kCachePath! + "/" + fileName!
        
        //检查当前路径是否已经下载了该文件
        if FileTool.fileExists(filePath: self.downLoadedPath!) {
            print("文件以及下载完成")
            return
        }
        
        print(self.downLoadingPath ?? "")
        
        //如果没有下载完成 就看是否有临时文件
        if !FileTool.fileExists(filePath: self.downLoadingPath!) {
            //不存在的话 直接开始下载
            self.downLoadWithURL(url as URL, 0)
            
            return;
        }
        
        
        //已经下载了的 先计算 下载的大小,然后继续下载
        tmpSize = FileTool.fileSize(self.downLoadingPath!)
        self.downLoadWithURL(url as URL, tmpSize)
        
    }
    
    
    // MARK:- 开始请求资源
    func downLoadWithURL(_ url : URL, _ offset : CLongLong) {
        
        var request = NSURLRequest(url: url, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringCacheData, timeoutInterval: 0) as URLRequest
        
        request.setValue("bytes=%lld-", forHTTPHeaderField: "Range")
        
       let dataTask = self.session.dataTask(with: request)
        
        dataTask.resume()
    }
    
    
}


extension DownLoader : URLSessionDataDelegate {
    
    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Swift.Void){
        
        print(response)
        let resp = response as! HTTPURLResponse
//        self.totalSize = resp.allHeaderFields["Content-Length"] as! CLongLong?
        
//        self.totalSize = String(resp.allHeaderFields["Content-Length"]).components(separatedBy: "/").last).CLongLong
        
        let string = resp.allHeaderFields["Content-Length"] as! String
        
        let stri : String = string.components(separatedBy: "/").last!
                
        self.totalSize = CLongLong(stri)!
        
        
        
       // 比对本地大小, 和 总大小
        if (self.tmpSize == self.totalSize) {
            
            // 1. 移动到下载完成文件夹
            print("移动文件到下载完成")
            FileTool.moveFile(self.downLoadingPath!, self.downLoadedPath!)
            // 2. 取消本次请求
            completionHandler(URLSession.ResponseDisposition.cancel);
            return;
        }
        
        if (self.tmpSize > self.totalSize) {
            
            // 1. 删除临时缓存
            print("删除临时缓存")
            FileTool.removeFile(self.downLoadingPath!)
            
            
            // 2. 从0 开始下载
            print("重新开始下载")
            self.downLoader(url: resp.url! as NSURL)
            //             [self downLoadWithURL:response.URL offset:0];
            // 3. 取消请求
            completionHandler(URLSession.ResponseDisposition.cancel);
            
            return;
            
        }
        
        
        
        // 继续接受数据
        // 确定开始下载数据
        self.outputStream = OutputStream(toFileAtPath: self.downLoadingPath!, append: true)
        
        self.outputStream?.open()
        completionHandler(URLSession.ResponseDisposition.allow);
        
        
        
    }
    
    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data){
        
        var buffer = [UInt8](repeating: 0, count: data.count)
        data.copyBytes(to: &buffer, count: data.count)
        
        self.outputStream?.write(buffer, maxLength: data.count)

        
//        let uint8Ptr = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count)
//        uint8Ptr.initialize(from: data)
//        let rawPtr = UnsafeRawPointer(uint8Ptr)
//        self.outputStream?.write(rawPtr, maxLength: da.length)

    }
    
    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?){
        
        print("请求完成")
        
        
        if (error == nil) {
            
            // 不一定是成功
            // 数据是肯定可以请求完毕
            // 判断, 本地缓存 == 文件总大小 {filename: filesize: md5:xxx}
            // 如果等于 => 验证, 是否文件完整(file md5 )
           
        }else {
            print("有问题")
        }
      
        self.outputStream?.close()      
        
    }
  
}

其次是文件的工具类 FileTool.swift

import UIKit

class FileTool: NSObject {

    
    // MARK:- 判断文件目录是否存在
    class func fileExists(filePath : String) -> Bool {
        
        if (filePath.characters.count == 0) {
            return false
        }
        return FileManager.default.fileExists(atPath: filePath)
    }
    
    // MARK:- 获取文件的大小
    class func  fileSize(_ filePath : String) ->CLongLong{
    
        if !self.fileExists(filePath: filePath) {
            return 0
        }
        
        let fileInfo = try! FileManager.default.attributesOfItem(atPath: filePath)
        
        return fileInfo[FileAttributeKey.size] as! CLongLong
        
    }
    
    // MARK:- 移动文件
    class func moveFile(_ fromPath : String , _ toPath : String){
        
        if self.fileSize(fromPath)  == 0 {
            return
        }
        try! FileManager.default.moveItem(atPath: fromPath, toPath: toPath)
    }
    
    class func removeFile(_ filePath : String){
       try! FileManager.default.removeItem(atPath: filePath)
    }
  
}

使用很简单

    fileprivate var downLoader = DownLoader()

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        
        let url = NSURL(string: "http://free2.macx.cn:8281/tools/photo/SnapNDragPro418.dmg")
        
        self.downLoader.downLoader(url: url!)
        
    }

<附上链接地址🙄>
下载链接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,383评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,522评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,852评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,621评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,741评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,929评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,076评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,803评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,265评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,582评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,716评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,395评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,039评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,027评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,488评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,612评论 2 350

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,066评论 4 62
  • 每年农历五月初五为端午节,是中国民间的传统节日,又称端阳节,重五节。端午节流行于汉、壮、布依、侗、土家、仡佬等名族...
    senny1978阅读 224评论 0 1
  • 过程重要还是结果重要?规划重要还是机会重要?工作重要还是亲朋好友重要? 如果你说都重要,肯定有人会接着问:“哪个更...
    楚丹丹阅读 526评论 0 2