214 lines
6.8 KiB
Objective-C
214 lines
6.8 KiB
Objective-C
//
|
||
// XPRoomFaceTool.m
|
||
// xplan-ios
|
||
//
|
||
// Created by 冯硕 on 2022/3/9.
|
||
//
|
||
|
||
#import "XPRoomFaceTool.h"
|
||
#import <SSZipArchive.h>
|
||
#import <AFNetworking.h>
|
||
#import <CommonCrypto/CommonDigest.h>
|
||
#define FileHashDefaultChunkSizeForReadingData 1024*8 // 8K
|
||
|
||
NSString * const kRoomFaceVersion = @"kRoomFaceVersion";
|
||
|
||
@interface XPRoomFaceTool ()
|
||
///解压缩之后 表情资源所在的位置
|
||
@property (nonatomic,copy) NSString *faceDirectory;
|
||
///重试的次数
|
||
@property (nonatomic,assign) NSInteger retryCount;
|
||
@end
|
||
|
||
@implementation XPRoomFaceTool
|
||
|
||
+ (instancetype)shareFaceTool {
|
||
static dispatch_once_t onceToken;
|
||
static XPRoomFaceTool * tool;
|
||
dispatch_once(&onceToken, ^{
|
||
tool = [[XPRoomFaceTool alloc] init];
|
||
tool.retryCount = 0;
|
||
});
|
||
return tool;
|
||
}
|
||
|
||
- (void)downFaceData {
|
||
[self downFaceDataCompletion:nil];
|
||
}
|
||
|
||
- (void)downFaceDataCompletion:(nullable void (^)(NSString * nullable))completion {
|
||
//获取沙盒doucument路径
|
||
NSArray*pathsss =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
|
||
NSString *documentsDirectory = [pathsss objectAtIndex:0];
|
||
NSString*faceDirectory = [documentsDirectory stringByAppendingPathComponent:@"Face"];
|
||
///首先判断 本地的数据是否 需要更新了
|
||
NSString *version = [[NSUserDefaults standardUserDefaults]objectForKey: kRoomFaceVersion];
|
||
if (version == nil || version.integerValue < self.version.integerValue) {///本地没有保存的话 就走下载
|
||
if (self.zipUrl.length > 0 && [self.zipUrl hasPrefix:@"http"]) {
|
||
NSURL *URL = [NSURL URLWithString:self.zipUrl];
|
||
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
|
||
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
|
||
//请求
|
||
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
|
||
//下载Task操作
|
||
[[manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
|
||
|
||
} destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
|
||
//要求返回一个URL, 返回的这个URL就是文件的位置的路径
|
||
NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
|
||
NSString *path = [cachesPath stringByAppendingPathComponent:response.suggestedFilename];
|
||
return [NSURL fileURLWithPath:path];
|
||
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
|
||
if (error == nil) {
|
||
NSString *filePathStr = [filePath path];
|
||
NSString *fileMD5Str = [self getFileMD5WithPath:filePathStr];
|
||
fileMD5Str = [fileMD5Str uppercaseString];
|
||
if (![self.zipMd5 isEqualToString:fileMD5Str]) { //MD5校验 如果不相等就重新下载
|
||
[self performSelector:@selector(downFaceData) withObject:nil afterDelay:3];
|
||
}else {
|
||
// filePath就是你下载文件的位置,你可以解压,也可以直接拿来使用
|
||
NSString *imgFilePath = [filePath path];
|
||
NSLog(@"img == %@", imgFilePath);
|
||
NSString *zipPath = imgFilePath;
|
||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||
//删除老的数据
|
||
[[NSFileManager defaultManager] removeItemAtPath:faceDirectory error:nil];
|
||
[fileManager createDirectoryAtPath:faceDirectory withIntermediateDirectories:YES attributes:nil error:nil];
|
||
NSLog(@"test == %@",faceDirectory); //解压后的路径
|
||
dispatch_async(dispatch_get_global_queue(0, 0), ^{
|
||
//解压
|
||
[SSZipArchive unzipFileAtPath:zipPath toDestination:faceDirectory overwrite:YES password:nil progressHandler:^(NSString * _Nonnull entry, unz_file_info zipInfo, long entryNumber, long total) {
|
||
|
||
} completionHandler:^(NSString * _Nonnull path, BOOL succeeded, NSError * _Nullable error) {
|
||
if (error == nil) {
|
||
self.retryCount = 0;
|
||
///如果解压完成的话 就保存一下值
|
||
[[NSUserDefaults standardUserDefaults]setObject:self.version forKey:kRoomFaceVersion];
|
||
self.faceDirectory = faceDirectory;
|
||
if (completion) {
|
||
completion(faceDirectory);
|
||
}
|
||
} else {
|
||
self.retryCount ++;
|
||
if (self.retryCount <=10) {
|
||
[self downFaceData];
|
||
}
|
||
if (completion) {
|
||
completion(nil);
|
||
}
|
||
}
|
||
}];
|
||
});
|
||
}
|
||
} else {
|
||
self.retryCount ++;
|
||
if (self.retryCount <=10) {
|
||
[self downFaceData];
|
||
}
|
||
if (completion) {
|
||
completion(nil);
|
||
}
|
||
}
|
||
|
||
}] resume];
|
||
} else {
|
||
if (completion) {
|
||
completion(nil);
|
||
}
|
||
}
|
||
} else {
|
||
self.faceDirectory = faceDirectory;
|
||
if (completion) {
|
||
completion(faceDirectory);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
- (NSString*)getFileMD5WithPath:(NSString*)path {
|
||
return (__bridge NSString *)FileMD5HashCreateWithPath((__bridge CFStringRef)path,FileHashDefaultChunkSizeForReadingData);
|
||
}
|
||
|
||
CFStringRef FileMD5HashCreateWithPath(CFStringRef filePath,
|
||
size_t chunkSizeForReadingData) {
|
||
|
||
// Declare needed variables
|
||
CFStringRef result = NULL;
|
||
CFReadStreamRef readStream = NULL;
|
||
|
||
// Get the file URL
|
||
CFURLRef fileURL =
|
||
CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
|
||
(CFStringRef)filePath,
|
||
kCFURLPOSIXPathStyle,
|
||
(Boolean)false);
|
||
|
||
CC_MD5_CTX hashObject;
|
||
bool hasMoreData = true;
|
||
bool didSucceed;
|
||
|
||
if (!fileURL) goto done;
|
||
|
||
// Create and open the read stream
|
||
readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault,
|
||
(CFURLRef)fileURL);
|
||
if (!readStream) goto done;
|
||
didSucceed = (bool)CFReadStreamOpen(readStream);
|
||
if (!didSucceed) goto done;
|
||
|
||
// Initialize the hash object
|
||
CC_MD5_Init(&hashObject);
|
||
|
||
// Make sure chunkSizeForReadingData is valid
|
||
if (!chunkSizeForReadingData) {
|
||
chunkSizeForReadingData = FileHashDefaultChunkSizeForReadingData;
|
||
}
|
||
|
||
// Feed the data to the hash object
|
||
while (hasMoreData) {
|
||
uint8_t buffer[chunkSizeForReadingData];
|
||
CFIndex readBytesCount = CFReadStreamRead(readStream,
|
||
(UInt8 *)buffer,
|
||
(CFIndex)sizeof(buffer));
|
||
if (readBytesCount == -1)break;
|
||
if (readBytesCount == 0) {
|
||
hasMoreData =false;
|
||
continue;
|
||
}
|
||
CC_MD5_Update(&hashObject,(const void *)buffer,(CC_LONG)readBytesCount);
|
||
}
|
||
|
||
// Check if the read operation succeeded
|
||
didSucceed = !hasMoreData;
|
||
|
||
// Compute the hash digest
|
||
unsigned char digest[CC_MD5_DIGEST_LENGTH];
|
||
CC_MD5_Final(digest, &hashObject);
|
||
|
||
// Abort if the read operation failed
|
||
if (!didSucceed) goto done;
|
||
|
||
// Compute the string result
|
||
char hash[2 *sizeof(digest) + 1];
|
||
for (size_t i =0; i < sizeof(digest); ++i) {
|
||
snprintf(hash + (2 * i),3, "%02x", (int)(digest[i]));
|
||
}
|
||
result = CFStringCreateWithCString(kCFAllocatorDefault,
|
||
(const char *)hash,
|
||
kCFStringEncodingUTF8);
|
||
|
||
done:
|
||
|
||
if (readStream) {
|
||
CFReadStreamClose(readStream);
|
||
CFRelease(readStream);
|
||
}
|
||
if (fileURL) {
|
||
CFRelease(fileURL);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
|
||
@end
|