美文网首页iOS OC 学习手册
Swift用URLSession实现文件的下载

Swift用URLSession实现文件的下载

作者: ziyouzhe4 | 来源:发表于2017-01-13 18:30 被阅读488次

    最近根据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!)
            
        }
    

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

    相关文章

      网友评论

        本文标题:Swift用URLSession实现文件的下载

        本文链接:https://www.haomeiwen.com/subject/uymsbttx.html