325 lines
15 KiB
Objective-C
325 lines
15 KiB
Objective-C
//
|
||
// UploadFile.m
|
||
// xplan-ios
|
||
//
|
||
// Created by GreenLand on 2022/2/23.
|
||
//
|
||
#import <QCloudCOSXML/QCloudCOSXML.h>
|
||
#import "UploadFile.h"
|
||
#import <AFNetworking.h>
|
||
#import "Api+Mine.h"
|
||
#import "UploadFileModel.h"
|
||
static UploadFile* manager;
|
||
|
||
@interface UploadFile()<QCloudSignatureProvider,QCloudCredentailFenceQueueDelegate>
|
||
// 一个脚手架实例
|
||
@property (nonatomic) QCloudCredentailFenceQueue* credentialFenceQueue;
|
||
@property(nonatomic,strong) UploadFileModel *fileModel;
|
||
@end
|
||
|
||
@implementation UploadFile
|
||
|
||
+ (instancetype)share {
|
||
static dispatch_once_t onceToken;
|
||
dispatch_once(&onceToken, ^{
|
||
manager = [[UploadFile alloc] init];
|
||
});
|
||
return manager;
|
||
}
|
||
|
||
-(void)initQCloud{
|
||
[Api getQCloudInfo:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
|
||
if (code == 200){
|
||
UploadFileModel *fileModel = [UploadFileModel modelWithDictionary:data.data];
|
||
self.fileModel = fileModel;
|
||
QCloudServiceConfiguration* configuration = [QCloudServiceConfiguration new];
|
||
configuration.appID = fileModel.appId;
|
||
QCloudCOSXMLEndPoint* endpoint = [[QCloudCOSXMLEndPoint alloc] init];
|
||
endpoint.regionName = fileModel.region;
|
||
// 使用 HTTPS
|
||
endpoint.useHTTPS = YES;
|
||
configuration.endpoint = endpoint;
|
||
// 密钥提供者为自己
|
||
configuration.signatureProvider = self;
|
||
// 初始化 COS 服务示例
|
||
[QCloudCOSXMLService registerDefaultCOSXMLWithConfiguration:configuration];
|
||
[QCloudCOSTransferMangerService registerDefaultCOSTransferMangerWithConfiguration:
|
||
configuration];
|
||
|
||
self.credentialFenceQueue = [QCloudCredentailFenceQueue new];
|
||
self.credentialFenceQueue.delegate = self;
|
||
|
||
}
|
||
}];
|
||
}
|
||
#pragma mark- QCloudSignatureProvider
|
||
- (void) signatureWithFields:(QCloudSignatureFields*)fileds
|
||
request:(QCloudBizHTTPRequest*)request
|
||
urlRequest:(NSMutableURLRequest*)urlRequst
|
||
compelete:(QCloudHTTPAuthentationContinueBlock)continueBlock
|
||
{
|
||
|
||
[Api getQCloudInfo:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
|
||
if (code == 200){
|
||
UploadFileModel *fileModel = [UploadFileModel modelWithDictionary:data.data];
|
||
QCloudCredential* credential = [QCloudCredential new];
|
||
|
||
|
||
// 临时密钥 SecretId
|
||
|
||
credential.secretID = fileModel.secretId;
|
||
// 临时密钥 SecretKey
|
||
|
||
credential.secretKey = fileModel.secretKey;
|
||
// 临时密钥 Token
|
||
|
||
credential.token = fileModel.sessionToken;
|
||
/** 强烈建议返回服务器时间作为签名的开始时间, 用来避免由于用户手机本地时间偏差过大导致的签名不正确(参数startTime和expiredTime单位为秒)
|
||
*/
|
||
credential.startDate = [NSDate dateWithTimeIntervalSince1970:fileModel.startTime]; // 单位是秒
|
||
credential.expirationDate = [NSDate dateWithTimeIntervalSince1970:fileModel.expireTime];// 单位是秒
|
||
|
||
|
||
QCloudAuthentationV5Creator* creator = [[QCloudAuthentationV5Creator alloc]
|
||
initWithCredential:credential];
|
||
// 注意 这里不要对urlRequst 进行copy以及mutableCopy操作
|
||
QCloudSignature *signature = [creator signatureForData:urlRequst];
|
||
continueBlock(signature, nil);
|
||
|
||
}
|
||
}
|
||
];
|
||
|
||
}
|
||
|
||
#pragma mark - QCloudCredentailFenceQueueDelegate
|
||
- (void) fenceQueue:(QCloudCredentailFenceQueue * )queue requestCreatorWithContinue:(QCloudCredentailFenceQueueContinue)continueBlock
|
||
{
|
||
//这里同步从◊后台服务器获取临时密钥,强烈建议将获取临时密钥的逻辑放在这里,最大程度上保证密钥的可用性
|
||
//...
|
||
|
||
[Api getQCloudInfo:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
|
||
if (code == 200){
|
||
UploadFileModel *fileModel = [UploadFileModel modelWithDictionary:data.data];
|
||
QCloudCredential* credential = [QCloudCredential new];
|
||
// 临时密钥 SecretId
|
||
credential.secretID = fileModel.secretId;
|
||
// 临时密钥 SecretKey
|
||
|
||
credential.secretKey = fileModel.secretKey;
|
||
// 临时密钥 Token
|
||
|
||
credential.token = fileModel.sessionToken;
|
||
/** 强烈建议返回服务器时间作为签名的开始时间, 用来避免由于用户手机本地时间偏差过大导致的签名不正确(参数startTime和expiredTime单位为秒)
|
||
*/
|
||
credential.startDate = [NSDate dateWithTimeIntervalSince1970:fileModel.startTime]; // 单位是秒
|
||
credential.expirationDate = [NSDate dateWithTimeIntervalSince1970:fileModel.expireTime];// 单位是秒
|
||
QCloudAuthentationV5Creator* creator = [[QCloudAuthentationV5Creator alloc]
|
||
initWithCredential:credential];
|
||
continueBlock(creator, nil);
|
||
}
|
||
}];
|
||
}
|
||
/// 上传一个文件
|
||
/// @param filePath 文件地址
|
||
/// @param fileName 文件的名字
|
||
/// @param success 成功
|
||
/// @param failure 失败
|
||
- (void)QCloudUploadFile:(NSString *)filePath
|
||
named:(NSString *)fileName
|
||
success:(void (^)(NSString *key, NSDictionary *resp))success
|
||
failure:(void (^)(NSNumber *resCode, NSString *message))failure {
|
||
|
||
|
||
QCloudCOSXMLUploadObjectRequest* put = [QCloudCOSXMLUploadObjectRequest new];
|
||
// 本地文件路径
|
||
NSURL* url = [NSURL fileURLWithPath:filePath];
|
||
// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket
|
||
put.bucket = self.fileModel.bucket;
|
||
// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"
|
||
put.object = fileName;
|
||
//需要上传的对象内容。可以传入NSData*或者NSURL*类型的变量
|
||
put.body = url;
|
||
//监听上传进度
|
||
[put setSendProcessBlock:^(int64_t bytesSent,
|
||
int64_t totalBytesSent,
|
||
int64_t totalBytesExpectedToSend) {
|
||
// bytesSent 本次要发送的字节数(一个大文件可能要分多次发送)
|
||
// totalBytesSent 已发送的字节数
|
||
// totalBytesExpectedToSend 本次上传要发送的总字节数(即一个文件大小)
|
||
}];
|
||
|
||
//监听上传结果
|
||
[put setFinishBlock:^(id outputObject, NSError *error) {
|
||
//可以从 outputObject 中获取 response 中 etag 或者自定义头部等信息
|
||
if (error) {
|
||
failure(@(error.code),error.localizedDescription);
|
||
return;
|
||
}
|
||
QCloudUploadObjectResult * result = (QCloudUploadObjectResult *)outputObject;
|
||
NSArray *urlList = [result.location componentsSeparatedByString:@".com/"];
|
||
if (urlList.count == 2){
|
||
NSString *url = [NSString stringWithFormat:@"%@/%@",self.fileModel.customDomain,urlList[1]];
|
||
success(url,nil);
|
||
return;
|
||
}
|
||
success(result.location,nil);
|
||
}];
|
||
|
||
[[QCloudCOSTransferMangerService defaultCOSTransferManager] UploadObject:put];
|
||
|
||
}
|
||
|
||
/// 上传一个Image
|
||
/// @param image 图片
|
||
/// @param imageName 图片的名字
|
||
|
||
/// @param success 成功
|
||
/// @param failure 失败
|
||
- (void)QCloudUploadImage:(NSData *)data
|
||
named:(NSString *)name
|
||
success:(void (^)(NSString *key, NSDictionary *resp))success
|
||
failure:(void (^)(NSNumber *resCode, NSString *message))failure{
|
||
|
||
QCloudCOSXMLUploadObjectRequest* put = [QCloudCOSXMLUploadObjectRequest new];
|
||
put.bucket = self.fileModel.bucket;
|
||
// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"
|
||
put.object = name;
|
||
//需要上传的对象内容。可以传入NSData*或者NSURL*类型的变量
|
||
put.body = data;
|
||
//监听上传进度
|
||
[put setSendProcessBlock:^(int64_t bytesSent,
|
||
int64_t totalBytesSent,
|
||
int64_t totalBytesExpectedToSend) {
|
||
// bytesSent 本次要发送的字节数(一个大文件可能要分多次发送)
|
||
// totalBytesSent 已发送的字节数
|
||
// totalBytesExpectedToSend 本次上传要发送的总字节数(即一个文件大小)
|
||
}];
|
||
|
||
//监听上传结果
|
||
[put setFinishBlock:^(id outputObject, NSError *error) {
|
||
|
||
if (error) {
|
||
failure(@(error.code),error.localizedDescription);
|
||
return;
|
||
}
|
||
QCloudUploadObjectResult * result = (QCloudUploadObjectResult *)outputObject;
|
||
NSArray *urlList = [result.location componentsSeparatedByString:@".com/"];
|
||
if (urlList.count == 2){
|
||
NSString *url = [NSString stringWithFormat:@"%@/%@",self.fileModel.customDomain,urlList[1]];
|
||
success(url,nil);
|
||
return;
|
||
}
|
||
success(result.location,nil);
|
||
}];
|
||
|
||
[[QCloudCOSTransferMangerService defaultCOSTransferManager] UploadObject:put];
|
||
}
|
||
|
||
-(void)downloadAnimationFileName:(NSString *)fileName localPath:(NSString *)localPath completion:(void (^) (BOOL isSuccess, NSString *editAudioPath))completion{
|
||
QCloudCOSXMLDownloadObjectRequest * request = [QCloudCOSXMLDownloadObjectRequest new];
|
||
|
||
|
||
// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket
|
||
request.bucket = self.fileModel.bucket;
|
||
|
||
NSArray *urlList = [fileName componentsSeparatedByString:@".com/"];
|
||
|
||
// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"
|
||
request.object = [urlList safeObjectAtIndex1:1];
|
||
|
||
|
||
// 设置下载的路径 URL,如果设置了,文件将会被下载到指定路径中
|
||
request.downloadingURL = [NSURL fileURLWithPath:localPath];
|
||
|
||
|
||
|
||
|
||
// 监听下载结果
|
||
[request setFinishBlock:^(id outputObject, NSError *error) {
|
||
// outputObject 包含所有的响应 http 头部
|
||
NSDictionary* info = (NSDictionary *) outputObject;
|
||
NSLog(@"%@",info);
|
||
}];
|
||
|
||
|
||
// 监听下载进度
|
||
[request setDownProcessBlock:^(int64_t bytesDownload,
|
||
int64_t totalBytesDownload,
|
||
int64_t totalBytesExpectedToDownload) {
|
||
|
||
|
||
// bytesDownload 新增字节数
|
||
// totalBytesDownload 本次下载接收的总字节数
|
||
// totalBytesExpectedToDownload 本次下载的目标字节数
|
||
}];
|
||
|
||
|
||
[[QCloudCOSTransferMangerService defaultCOSTransferManager] DownloadObject:request];
|
||
|
||
}
|
||
+(void)downloadAudioWithFileName:(NSString *)fileName musicUrl:(NSString *)musicUrl mainFileName:(NSString *)mainFileName completion:(void (^) (BOOL isSuccess, NSString *editAudioPath))completion {
|
||
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
|
||
NSURL *url = [NSURL URLWithString:[musicUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]];
|
||
NSURLRequest *request = [NSURLRequest requestWithURL :url];
|
||
NSURLSessionDownloadTask *download = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
|
||
} destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
|
||
NSString *filePath = [[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) safeObjectAtIndex1:0] stringByAppendingPathComponent:mainFileName] stringByAppendingPathComponent:fileName];
|
||
return [NSURL fileURLWithPath:filePath];
|
||
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
|
||
if (!error) {
|
||
completion(YES, filePath.path);
|
||
} else {
|
||
completion(NO, nil);
|
||
}
|
||
}];
|
||
[download resume];
|
||
}
|
||
|
||
+(void)downloadGiftDynamicEffectWithList:(NSSet *)list completion:(void (^) (BOOL isSuccess, NSMutableArray *editAudioPath))completion{
|
||
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
|
||
manager.operationQueue.maxConcurrentOperationCount = 20; // 控制并发数量
|
||
dispatch_group_t requestGroup = dispatch_group_create();
|
||
NSMutableArray *failList = [NSMutableArray array];
|
||
|
||
for (NSString *giftUrl in list) {
|
||
NSString *encodingUrl = [giftUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@"`#%^{}\"[]|\\<> "].invertedSet];
|
||
NSString *fileName = [[encodingUrl componentsSeparatedByString:@"/"] lastObject];
|
||
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) safeObjectAtIndex1:0] stringByAppendingPathComponent:@"GiftDynamicEffectList"];
|
||
NSString *fullPath = [filePath stringByAppendingPathComponent:fileName];
|
||
if ([[NSFileManager defaultManager] fileExistsAtPath:fullPath]) {
|
||
continue;
|
||
}
|
||
NSFileManager *fileMgr = [[NSFileManager alloc] init];
|
||
[fileMgr createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:nil];
|
||
dispatch_group_enter(requestGroup);
|
||
NSURL *url = [NSURL URLWithString:[encodingUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]];
|
||
NSURLRequest *request = [NSURLRequest requestWithURL :url];
|
||
NSURLSessionDownloadTask *download = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
|
||
} destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
|
||
return [NSURL fileURLWithPath:fullPath];
|
||
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
|
||
dispatch_group_leave(requestGroup);
|
||
if (!error) {
|
||
NSLog(@"下载完成");
|
||
} else {
|
||
NSLog(@"下载失败");
|
||
[failList addObject:encodingUrl];
|
||
}
|
||
}];
|
||
[download resume];
|
||
}
|
||
dispatch_group_notify(requestGroup, dispatch_get_main_queue(), ^{
|
||
if(failList.count > 0){
|
||
completion(NO,failList);
|
||
NSLog(@"下载有失败");
|
||
}else{
|
||
NSLog(@"下载全部完成");
|
||
completion(NO,nil);
|
||
}
|
||
});
|
||
|
||
}
|
||
|
||
@end
|