//生成一個downloadTask
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue())
self.session = session
let dataTask = session.downloadTask(with: request)
// 開始請求
dataTask.resume()
下載下傳的網絡請求并不難,還可以擷取下載下傳進度,在完成的時候拿到回調一定要提前移出來,不然系統會自動銷毀
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask,
didWriteData bytesWritten: Int64,
totalBytesWritten: Int64,
totalBytesExpectedToWrite: Int64) {
//擷取進度
let written = (Float)(totalBytesWritten)
let total = (Float)(totalBytesExpectedToWrite)
let pro = written/total
if let downLoadProgress = downLoadProgress {
downLoadProgress(pro)
}
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
if let completionHandler = completionHandlerBlock {
var tempError: Error?
do {
try FileManager.default.moveItem(atPath: location.path, toPath: tempPath ?? downloadTask.response?.suggestedFilename ?? "*.text")
} catch {
tempError = error
}
//完成任務,
session.finishTasksAndInvalidate()
//清空Session
self.session = nil
completionHandler(location, tempError)
}
}
下載下傳下來并不難,剩下的是我們需要做一個存儲,我是根據背景的ID來判斷檔案的唯一性,如果一個檔案多次接收,隻要檔案ID一樣,就可以直下載下傳一次,當然檔案是否真的是同一個檔案是要根據檔案的 hash值等操作來判斷的,也許同名但内容有改變,也有内容一樣隻是重命名了,具體并沒有在移動端實作,是以我并沒有深入研究,後端會判斷好,反給我檔案的ID,ID一樣的我就認為是同一個檔案就可以了
存儲的時候,用ID 然後MD5 加密是最簡單和直覺來判斷是否存在的命名方式了
下面是實作方式:
lazy var tempDirectory: String = {
let tempPath = NSTemporaryDirectory()
return tempPath
}()
lazy var cacheDirectory: String = {
let cache = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.cachesDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let cachePath = cache[0]
return cachePath
}()
// 檔案存儲路徑 需要拼接檔案名
lazy var fileCachePath: String = {
let directoryPath = cacheDirectory.appending("/APPName")
if !FileManager.default.fileExists(atPath: directoryPath) {
try? FileManager.default.createDirectory(atPath: directoryPath, withIntermediateDirectories: true, attributes: nil)
}
return directoryPath
}()
// 判斷檔案是否存在
class func judgeFileIsExist(_ filePath: String) -> Bool {
return FileManager.default.fileExists(atPath: filePath)
}
// MARK: ...移動檔案
class func moveFile(_ fromPath: String, _ toPath: String) {
if self.getFileSizeWithFileName(fromPath) == 0 {
return
}
try? FileManager.default.moveItem(atPath: fromPath, toPath: toPath)
}
// 建立檔案
class func creatFile(_ filePath: String, isDirectories: Bool = false) {
if !FileManager.default.fileExists(atPath: filePath) {
try? FileManager.default.createDirectory(atPath: filePath, withIntermediateDirectories: isDirectories, attributes: nil)
}
}
// 删除檔案
class func deleteFile(_ filePath: String) {
if FileManager.default.fileExists(atPath: filePath) {
do {
try FileManager.default.removeItem(atPath: filePath)
} catch {
debugPrint("\(error)")
}
}
}
// 計算檔案大小
class func getFileSizeWithFileName(_ path: String) -> UInt64 {
// 1.檔案總大小
var totalSize: UInt64 = 0
// 2.建立檔案管理者
let fileManager = FileManager.default
// 3.判斷檔案存不存在以及是否是檔案夾
var isDirectory: ObjCBool = ObjCBool(false)
let isFileExist = fileManager.fileExists(atPath: path, isDirectory: &isDirectory)
if !isFileExist {
return totalSize
} // 檔案不存在
if (isDirectory).boolValue { // 是檔案夾
guard let subPaths = fileManager.subpaths(atPath: path) else {
return totalSize
}
for subPath in subPaths {
let filePath = path.appendingFormat("/%@", subPath)
var isDirectory: ObjCBool = ObjCBool(false)
let isExistFile = fileManager.fileExists(atPath: filePath, isDirectory: &isDirectory)
if !isDirectory.boolValue && isExistFile && !filePath.contains("DS") {
do {
if let attr: NSDictionary = try fileManager.attributesOfItem(atPath: path) as NSDictionary? {
totalSize += attr.fileSize()
}
} catch {
debugPrint("Error: \(error)")
}
}
}
} else { // 不是檔案夾
do {
if let attr: NSDictionary = try fileManager.attributesOfItem(atPath: path) as NSDictionary? {
totalSize += attr.fileSize()
}
} catch {
debugPrint("Error: \(error)")
}
}
return totalSize
}
這樣就封裝好了一個工具類,使用的時候調用這個工具類就可以了
/**
* 判斷檔案是否存在,判斷是否可以下載下傳(檔案不存在說明可以下載下傳,因為下面的下載下傳
* 是存在臨時檔案的,下載下傳好了才存到真正的路徑(是以不需要去判斷檔案的大小)
*/
func judgeFileIsExist(with content: MessageContent) -> Bool {
let fileName = getFileName(fileId: content.fileId, fileType: content.fileType)
let filePath = DiskCacheTool.shared.fileCachePath + "/" + fileName
return DiskCacheTool.judgeFileIsExist(filePath)
}
func getFileName(fileId: Int64?, fileType: String?) -> String {
let idString = String(format: "%d", fileId ?? "")
let fileName = String(format: "%@.%@", idString.MD5, fileType?.lowercased() ?? "")
return fileName
}