最近根據(jù)URLSession 實(shí)現(xiàn)文件的下載,簡(jiǎn)單地封裝了一下注釋很詳細(xì),這里不再過多的贅述,喜歡的可以看看.
- 1 FileTool.swift 實(shí)現(xiàn)獲取文件的大小/移動(dòng)文件/文件是否存在等等的判斷
- 2 DownLoader.swift 是下載文件的主類
- 3在Controller中創(chuàng)建DownLoader對(duì)象,即可使用
??
首先是 下載的類 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!
//檢查當(dāng)前路徑是否已經(jīng)下載了該文件
if FileTool.fileExists(filePath: self.downLoadedPath!) {
print("文件以及下載完成")
return
}
print(self.downLoadingPath ?? "")
//如果沒有下載完成 就看是否有臨時(shí)文件
if !FileTool.fileExists(filePath: self.downLoadingPath!) {
//不存在的話 直接開始下載
self.downLoadWithURL(url as URL, 0)
return;
}
//已經(jīng)下載了的 先計(jì)算 下載的大小,然后繼續(xù)下載
tmpSize = FileTool.fileSize(self.downLoadingPath!)
self.downLoadWithURL(url as URL, tmpSize)
}
// MARK:- 開始請(qǐng)求資源
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)!
// 比對(duì)本地大小, 和 總大小
if (self.tmpSize == self.totalSize) {
// 1. 移動(dòng)到下載完成文件夾
print("移動(dòng)文件到下載完成")
FileTool.moveFile(self.downLoadingPath!, self.downLoadedPath!)
// 2. 取消本次請(qǐng)求
completionHandler(URLSession.ResponseDisposition.cancel);
return;
}
if (self.tmpSize > self.totalSize) {
// 1. 刪除臨時(shí)緩存
print("刪除臨時(shí)緩存")
FileTool.removeFile(self.downLoadingPath!)
// 2. 從0 開始下載
print("重新開始下載")
self.downLoader(url: resp.url! as NSURL)
// [self downLoadWithURL:response.URL offset:0];
// 3. 取消請(qǐng)求
completionHandler(URLSession.ResponseDisposition.cancel);
return;
}
// 繼續(xù)接受數(shù)據(jù)
// 確定開始下載數(shù)據(jù)
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("請(qǐng)求完成")
if (error == nil) {
// 不一定是成功
// 數(shù)據(jù)是肯定可以請(qǐng)求完畢
// 判斷, 本地緩存 == 文件總大小 {filename: filesize: md5:xxx}
// 如果等于 => 驗(yàn)證, 是否文件完整(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:- 移動(dòng)文件
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)
}
}
使用很簡(jiǎn)單
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!)
}
<附上鏈接地址??>
下載鏈接