Music_Player3/relax.offline.mp3.music/MP/Common/Tool(工具封装)/MP_CacheManager.swift

299 lines
11 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// MP_CacheManager.swift
// MusicPlayer
//
// Created by Mr.Zhou on 2024/5/23.
//
import Foundation
////
class MP_CacheAndArchiverManager {
// 访
static let shared = MP_CacheAndArchiverManager()
//
let fileManager = FileManager.default
///
// private var archiverDic:[String: MP_PlayerRequestModel]!
///
private var isCompleteds:[String:Bool] = [:]
//
private var zhoujunfeng_cacheOutTimes:TimeInterval = 172800
private init() {
}
///
func zhoujunfeng_checkAndCleanCacheFolder() {
//URL
let contents:[URL]!
guard let cacheDirectory = createCachePath() else {return}
do{
contents = try fileManager.contentsOfDirectory(at: URL(fileURLWithPath: cacheDirectory), includingPropertiesForKeys: [.creationDateKey], options: .skipsHiddenFiles)
}catch {
print("获取缓存文件夹内容失败:\(error.localizedDescription)")
return
}
//
var folderSize: UInt64 = 0
for content in contents {
if let fileSize = try? content.resourceValues(forKeys: [.fileSizeKey]).fileSize {
folderSize += UInt64(fileSize)
}
}
//
if folderSize > 1024 * 1024 * 1024 * 2 {
let sortedFiles = contents.sorted { (url1, url2) -> Bool in
let creationDate1 = try? url1.resourceValues(forKeys: [.creationDateKey]).creationDate
let creationDate2 = try? url2.resourceValues(forKeys: [.creationDateKey]).creationDate
return creationDate1 ?? Date() < creationDate2 ?? Date()
}
for file in sortedFiles {
print("清理\(file.absoluteString)的缓存文件")
try? fileManager.removeItem(at: file)
folderSize -= UInt64((try? file.resourceValues(forKeys: [.fileSizeKey]).fileSize) ?? 0)
if folderSize <= 1024 * 1024 * 1024 * 2 {
break
}
}
}
}
///
func cleanAllCache(_ compleHandler:((Bool) -> Void)?) {
guard let cacheDirectory = createCachePath() else {return}
//
do{
let contents = try fileManager.contentsOfDirectory(atPath: cacheDirectory)
for item in contents {
let itemPath = (cacheDirectory as NSString).appendingPathComponent(item)
print("清理\(item)的缓存文件")
try fileManager.removeItem(atPath: itemPath)
}
//
print("已清理了所有缓存数据")
if let block = compleHandler {
block(true)
}
}catch{
print("Error clearing folder contents: \(error.localizedDescription)")
if let block = compleHandler {
block(false)
}
}
}
///
func createCachePath() -> String? {
// CacheMP_PlayerCache
let cacheDirectory = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first!
let path = cacheDirectory+"/"+"MP_PlayerCache"
//
guard fileManager.fileExists(atPath: path) == false else {
//
return path
}
//
do {
//
try fileManager.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
return path
} catch {
//
print("创建播放器缓存文件夹失败,失败原因:\(error)")
return nil
}
}
///
func createTempFile(_ videoID:String) -> Bool {
//
let path = tempPath(videoID)
if fileManager.fileExists(atPath: path) {
//
do{
try fileManager.removeItem(atPath: path)
}catch {
print("删除临时文件失败error: \(error)")
}
}
//
return fileManager.createFile(atPath: path, contents: nil, attributes: nil)
}
///
func writeDataToAudioFileTempPathWithData(_ data:Data, videoId:String) {
guard let handle = FileHandle(forWritingAtPath: tempPath(videoId)) else {return}
if #available(iOS 13.4, *) {
do{
try handle.seekToEnd()
}catch {
print("Seek到末尾失败失败原因:\(error)")
}
} else {
handle.seekToEndOfFile()
}
//
if #available(iOS 13.4, *) {
do{
try handle.write(contentsOf: data)
}catch{
print("写入数据失败,失败原因:\(error)")
}
} else {
handle.write(data)
}
do {
if #available(iOS 13.4, *) {
try? handle.close() //
} else {
handle.closeFile()
}
}
}
///
func readTempFileDataWithOffset(_ offset:UInt64, length:Int, videoId:String) -> Data? {
var allhandle:FileHandle!
//
if isCompleteds[videoId] == true {
//
let path = audioCachedPath() ?? ""
let audioName = "/"+videoId+".mp4"
let cachePath = path+audioName
guard let handle = FileHandle(forReadingAtPath: cachePath) else {return nil}
allhandle = handle
}else {
let path = tempPath(videoId)
guard let handle = FileHandle(forReadingAtPath: path) else {return nil}
allhandle = handle
}
if #available(iOS 13.0, *) {
do{
try allhandle.seek(toOffset: offset)
}catch{
print("Seek到指定位置失败失败原因:\(error)")
try? allhandle.close()
}
} else {
allhandle.seek(toFileOffset: offset)
}
if #available(iOS 13.4, *) {
do{
let data = try allhandle.read(upToCount: length)
try allhandle.close()
return data
}catch{
print("读取到指定位置失败,失败原因:\(error)")
return nil
}
} else {
let data = allhandle.readData(ofLength: length)
allhandle.closeFile()
return data
}
}
///
/// - Parameter videoId: 使videoId
func moveAudioFileFromTempPathToCachePath(_ videoId: String) -> Bool {
guard let path = audioCachedPath() else {return false }
// 1.
if !(fileManager.fileExists(atPath: path)) {
//
do{
try fileManager.createDirectory(atPath: path, withIntermediateDirectories: true)
}catch {
print("创建缓存夹失败,失败原因:\(error)")
return false
}
}
let audioName = "/"+videoId+".mp4"
let cachePath = path+audioName
//
if fileManager.fileExists(atPath: cachePath) {
// do {
// print("")
// try fileManager.removeItem(atPath: cachePath)
// } catch {
// print(": \(error)")
// return false
// }
return true
}
// 2.
let tempFilePath = tempPath(videoId)
guard fileManager.fileExists(atPath: tempFilePath) else {
// print(": \(tempFilePath)")
return false
}
// 3.
do {
try fileManager.moveItem(atPath: tempFilePath, toPath: cachePath)
// print("\(videoId):\(cachePath)")
//
isCompleteds[videoId] = true
return true
} catch {
print("移动 \(videoId) 缓存文件失败,失败原因: \(error)")
// deleteKeyValueIfHaveArchivedWithVideoId(videoId) //
return false
}
}
///
private func audioCachedPath() -> String? {
return (createCachePath() ?? "")
}
///
private func tempPath(_ videoID:String) -> String {
return (NSTemporaryDirectory())+"/"+"\(videoID).mp4"
}
///VideoID
func zhoujunfeng_getCachePath(_ videoId:String) -> String? {
//
guard let path = MP_CacheAndArchiverManager.shared.createCachePath() else {
return nil
}
//videoId
let audioName = "/"+videoId+".mp4"
//
let audioPath = path+audioName
//
if fileManager.fileExists(atPath: audioPath) {
var attributes:[FileAttributeKey : Any]
//
do{
//
attributes = try fileManager.attributesOfItem(atPath: audioPath)
}catch {
//
print("获取\(videoId)的属性失败,失败原因:\(error.localizedDescription)")
return nil
}
//
if let creationDate = attributes[.creationDate] as? Date {
// print("\(videoId)",creationDate)
//
if Date().timeIntervalSince(creationDate) < zhoujunfeng_cacheOutTimes {
//
return audioPath
}else {
//
zhoujunfeng_deleteCachePath(audioPath, videoId: videoId)
return nil
}
} else {
print("\(videoId)无法获取文件的创建时间。")
return nil
}
}else {
//
return nil
}
}
//
func zhoujunfeng_deleteCachePath(_ path:String, videoId:String) {
do{
try fileManager.removeItem(atPath: path)
print("\(videoId)的缓存文件已经删除")
}catch{
print("\(videoId)的缓存文件删除失败,失败原因:\(error.localizedDescription)")
}
}
}