最近根据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!)
}
<附上链接地址🙄>
下载链接