Commit 297215daff4f9bed2654a5441326541ee41765e5

Authored by 梁星国
1 parent 24b6b846

提交更改

CNLiveUploadManager.podspec
... ... @@ -134,6 +134,11 @@ TODO:加入压缩测试
134 134 # s.requires_arc = true
135 135  
136 136 # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" }
137   - # s.dependency "JSONKit", "~> 1.4"
  137 + # 依赖类库
  138 + s.dependency "AFNetworking", "~> 3.1.0"
  139 + s.dependency "Qiniu", "~> 7.1"
  140 + s.dependency "PLShortVideoKit", "~> 1.13.1"
  141 + s.dependency "PLPlayerKit", "~> 3.3.3"
  142 +
138 143  
139 144 end
... ...
CNLiveUploadManager/util/CNTools.h 0 → 100644
  1 +//
  2 +// CNTools.h
  3 +// CNLiveNetAdd
  4 +//
  5 +// Created by 张旭 on 2017/12/30.
  6 +// Copyright © 2017年 cnlive. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +NS_ASSUME_NONNULL_BEGIN
  12 +
  13 +#ifndef AppId
  14 +#define AppId @"802_jhlqbq4475"
  15 +#endif
  16 +
  17 +@interface CNTools : NSObject
  18 +
  19 ++ (NSString *_Nullable)getyyMMdd;
  20 +
  21 ++ (NSString *)get13tsRandTimeStr;
  22 +
  23 ++ (NSString *)getSpid;
  24 +
  25 +@end
  26 +NS_ASSUME_NONNULL_END
... ...
CNLiveUploadManager/util/CNTools.m 0 → 100644
  1 +//
  2 +// CNTools.m
  3 +// CNLiveNetAdd
  4 +//
  5 +// Created by 张旭 on 2017/12/30.
  6 +// Copyright © 2017年 cnlive. All rights reserved.
  7 +//
  8 +
  9 +#import "CNTools.h"
  10 +
  11 +
  12 +@interface CNTools ()
  13 +
  14 +
  15 +@end
  16 +
  17 +@implementation CNTools
  18 +
  19 ++ (NSString *)getyyMMdd
  20 +{
  21 + //实例化一个NSDateFormatter对象
  22 + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  23 + //设定时间格式,这里可以设置成自己需要的格式
  24 + [dateFormatter setDateFormat:@"yyyy/MM/dd"];
  25 + //用[NSDate date]可以获取系统当前时间
  26 + NSString *currentDateStr = [dateFormatter stringFromDate:[NSDate date]];
  27 + return currentDateStr;
  28 +}
  29 +
  30 +#pragma mark 获得一个 13时间戳+八位随机数
  31 ++ (NSString *)get13tsRandTimeStr
  32 +{
  33 + NSString *str1 = [NSString stringWithFormat:@"%d",arc4random() % 10];
  34 + NSString *str2 = [NSString stringWithFormat:@"%d",arc4random() % 10];
  35 + NSString *str3 = [NSString stringWithFormat:@"%d",arc4random() % 10];
  36 + NSString *str4 = [NSString stringWithFormat:@"%d",arc4random() % 10];
  37 + NSString *str5 = [NSString stringWithFormat:@"%d",arc4random() % 10];
  38 + NSString *str6 = [NSString stringWithFormat:@"%d",arc4random() % 10];
  39 + NSString *str7 = [NSString stringWithFormat:@"%d",arc4random() % 10];
  40 + NSString *str8 = [NSString stringWithFormat:@"%d",arc4random() % 10];
  41 +
  42 + NSString *timeStamp = [NSString stringWithFormat:@"%ld",[self getNow13NumTimestamp]];
  43 +
  44 + NSString *randTimeStr = [NSString stringWithFormat:@"%@%@%@%@%@%@%@%@%@",timeStamp,str1,str2,str3,str4,str5,str6,str7,str8];
  45 + return randTimeStr;
  46 +}
  47 +
  48 ++ (NSInteger)getNowTimestamp{
  49 + NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
  50 + [formatter setDateStyle:NSDateFormatterMediumStyle];
  51 + [formatter setTimeStyle:NSDateFormatterShortStyle];
  52 + [formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"]; // ----------设置你想要的格式,hh与HH的区别:分别表示12小时制,24小时制
  53 + //设置时区,这个对于时间的处理有时很重要
  54 + NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"];
  55 + [formatter setTimeZone:timeZone];
  56 + NSDate *datenow = [NSDate date];//现在时间
  57 +// NSLog(@"设备当前的时间:%@",[formatter stringFromDate:datenow]);
  58 + //时间转时间戳的方法:
  59 + NSInteger timeSp = [[NSNumber numberWithDouble:[datenow timeIntervalSince1970]] integerValue];
  60 +// NSLog(@"设备当前的10位时间戳:%ld",(long)timeSp); //时间戳的值
  61 + return timeSp;
  62 +}
  63 +
  64 ++ (NSInteger)getNow13NumTimestamp{
  65 + NSInteger timeStamp10 = [self getNowTimestamp];
  66 +// NSLog(@"设备当前的13位时间戳:%ld",(long)timeSp); //时间戳的值
  67 + return timeStamp10* 1000;
  68 +}
  69 +
  70 +
  71 ++ (NSString *)getSpid
  72 +{
  73 + NSString *spId = @"";
  74 + NSArray *array = [AppId componentsSeparatedByString:@"_"];
  75 + spId = [array firstObject];
  76 + return spId;
  77 +}
  78 +
  79 +
  80 +@end
... ...
CNLiveUploadManager/util/HttpService.h 0 → 100644
  1 +//
  2 +// HttpService.h
  3 +// ZXBaseProject
  4 +//
  5 +// Created by 张旭 on 2017/1/12.
  6 +// Copyright © 2017年 cnlive. All rights reserved.
  7 +//
  8 +
  9 +////////////////////////////////////////////////////////
  10 +//////////// 基础网络请求
  11 +////////////////////////////////////////////////////////
  12 +
  13 +#import <Foundation/Foundation.h>
  14 +
  15 +typedef NS_ENUM(NSUInteger, HTTP_REQUEST_METHOD) {
  16 + E_HTTP_REQUEST_METHOD_GET = 0,
  17 + E_HTTP_REQUEST_METHOD_POST,
  18 +};
  19 +
  20 +typedef void(^completionHandler)(id data,NSError *error);
  21 +
  22 +@interface HttpService : NSObject
  23 +
  24 +/** 单例 */
  25 ++ (HttpService*)service;
  26 +
  27 +/** 清除所有任务 */
  28 +- (void)cleanAllTask;
  29 +
  30 +/** 所有网络请求的基础 */
  31 +- (NSURLSessionDataTask *)sendRequestWithHttpMethod:(HTTP_REQUEST_METHOD)method URLPath:(NSString *)pathStr parameters:(id)parameters isCache:(BOOL)isCache CheckParam:(NSArray *)checkParam completionHandler:(completionHandler)completionHandler;
  32 +
  33 +-(void)postWithUrlString:(NSString *)url parameters:(id)parameters completionHandler:(completionHandler)completionHandler;
  34 +
  35 +////////网++ 加密相关接口 网络
  36 +- (NSURLSessionDataTask *)sendEncRequestWithHttpMethod:(HTTP_REQUEST_METHOD)method URLPath:(NSString *)pathStr parameters:(id)parameters completionHandler:(completionHandler)completionHandler;
  37 +
  38 +@end
... ...
CNLiveUploadManager/util/HttpService.m 0 → 100644
  1 +//
  2 +// HttpService.m
  3 +// ZXBaseProject
  4 +//
  5 +// Created by 张旭 on 2017/1/12.
  6 +// Copyright © 2017年 cnlive. All rights reserved.
  7 +//
  8 +
  9 +#import "HttpService.h"
  10 +//#import "CNHttpLocalServer.h"
  11 +//#import "CNNetworkLogManager.h"
  12 +//static NSString *errorCode = @"errorCode";
  13 +//static NSString *errorMessage = @"errorMessage";
  14 +//static NSString *requestData = @"data";
  15 +
  16 +@interface HttpService ()
  17 +{
  18 +// AFHTTPSessionManager *_dataSessionManager;
  19 +}
  20 +
  21 +@end
  22 +
  23 +@implementation HttpService
  24 +//
  25 +//#pragma mark -
  26 +//#pragma mark - SINGLETON
  27 +//
  28 +//static HttpService * __singleton__;
  29 +//
  30 +//+ (HttpService *)service {
  31 +// static dispatch_once_t predicate;
  32 +// dispatch_once( &predicate, ^{ __singleton__ = [[[self class] alloc] init]; } );
  33 +// return __singleton__;
  34 +//}
  35 +//
  36 +//#pragma mark -
  37 +//#pragma mark - Init
  38 +//
  39 +//- (instancetype)init {
  40 +// self = [super init];
  41 +// if (self) {
  42 +// [self initManagers];
  43 +// }
  44 +// return self;
  45 +//}
  46 +//
  47 +///** 所有网络请求的基础 */
  48 +//- (NSURLSessionDataTask *)sendRequestWithHttpMethod:(HTTP_REQUEST_METHOD)method URLPath:(NSString *)pathStr parameters:(id)parameters isCache:(BOOL)isCache CheckParam:(NSArray *)checkParam completionHandler:(completionHandler)completionHandler
  49 +//{
  50 +// dispatch_async(dispatch_get_main_queue(), ^{
  51 +// [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
  52 +//
  53 +// });
  54 +// NSMutableDictionary *para = [CNTools encryptionSignWithParameter:[NSMutableDictionary dictionaryWithDictionary:parameters] encryptionKey:APPKey];
  55 +//
  56 +// NSString *urlStr = [[NSURL URLWithString:pathStr relativeToURL:_dataSessionManager.baseURL] absoluteString];
  57 +// NSString *methodStr = [self stringWithMethod:method];
  58 +//
  59 +// if (completionHandler && isCache) {
  60 +// [CNHttpLocalServer cacheForURL:urlStr parameters:para CheckParam:checkParam == nil ?@[]:checkParam withBlock:^(id<NSCoding> object) {
  61 +// if (object != nil) completionHandler(object,nil);
  62 +// }];
  63 +// }
  64 +// NSDictionary * dic = [CNHttpLocalServer cacheForURL:urlStr parameters:para CheckParam:checkParam == nil ?@[]:checkParam];
  65 +//// [IMAPlatform sharedInstance].isConnected
  66 +// if (![[[NSUserDefaults standardUserDefaults] objectForKey:CNConnectSuccNotification] boolValue] && dic == nil && completionHandler) {
  67 +// completionHandler(nil,[NSError errorWithDomain:@"暂无网络" code:-1001 userInfo:nil]);
  68 +// return nil;
  69 +// };
  70 +//
  71 +// NSMutableURLRequest *request = [_dataSessionManager.requestSerializer requestWithMethod:methodStr URLString:urlStr parameters:para error:nil];
  72 +// __block NSURLSessionDataTask *task = nil;
  73 +// task = [_dataSessionManager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {//
  74 +// [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
  75 +// NSError *err = nil;
  76 +// id data = nil;
  77 +// if(error ) {
  78 +// err = error;
  79 +//#if DEBUG
  80 +// [[CNNetworkLogManager defaultManager] showErrorLogWithResponse:error];
  81 +//#else
  82 +// if (error.code == 500 || error.code == 404) return;
  83 +//#endif
  84 +// }else {
  85 +// NSDictionary * responseObjectDic = [responseObject mj_keyValues];
  86 +//
  87 +// NSString *resultCode = [NSString stringWithFormat:@"%@", responseObjectDic[errorCode]];
  88 +//
  89 +// if([resultCode isEqualToString:@"0"]) {
  90 +// data = responseObjectDic[requestData];
  91 +// } else {
  92 +// err = [[NSError alloc] initWithDomain:responseObjectDic[errorMessage] code:[resultCode integerValue] userInfo:nil];
  93 +// }
  94 +// }
  95 +//
  96 +// dispatch_async(dispatch_get_main_queue(), ^{
  97 +// completionHandler(data, err);
  98 +// if ((data || [CNHttpLocalServer cacheForURL:urlStr parameters:para CheckParam:checkParam == nil ?@[]:checkParam] == nil) && isCache) {
  99 +// [CNHttpLocalServer setCache:data URL:urlStr parameters:para CheckParam:checkParam == nil ? @[]:checkParam];
  100 +// }
  101 +// });
  102 +//
  103 +// }];
  104 +// [task resume];
  105 +// return task;
  106 +//}
  107 +//-(void)postWithUrlString:(NSString *)url parameters:(id)parameters completionHandler:(completionHandler)completionHandler
  108 +//{
  109 +//
  110 +// AFHTTPSessionManager *mag = [AFHTTPSessionManager manager];
  111 +// [mag POST:url parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
  112 +//
  113 +// } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
  114 +// completionHandler(responseObject,nil);
  115 +//
  116 +// } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
  117 +// completionHandler(nil,error);
  118 +// }];
  119 +// return ;
  120 +// NSURL *nsurl = [NSURL URLWithString:url];
  121 +// NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:nsurl];
  122 +//
  123 +// //设置请求类型
  124 +// request.HTTPMethod = @"POST";
  125 +// NSData *data = [NSJSONSerialization dataWithJSONObject:parameters options:NSJSONWritingPrettyPrinted error:nil];
  126 +// //把参数放到请求体内
  127 +// NSString *postStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  128 +// request.HTTPBody = [postStr dataUsingEncoding:NSUTF8StringEncoding];
  129 +//
  130 +// NSURLSession *session = [NSURLSession sharedSession];
  131 +// NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
  132 +// if (error) { //请求失败
  133 +// completionHandler(nil , error);
  134 +// } else { //请求成功
  135 +// NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves error:nil];
  136 +// completionHandler(dic , error);
  137 +// NSLog(@"dic == %@",dic);
  138 +// }
  139 +// }];
  140 +// [dataTask resume]; //开始请求
  141 +//}
  142 +//
  143 +//////////网++ 加密相关接口 网络
  144 +//- (NSURLSessionDataTask *)sendEncRequestWithHttpMethod:(HTTP_REQUEST_METHOD)method URLPath:(NSString *)pathStr parameters:(id)parameters completionHandler:(completionHandler)completionHandler
  145 +//{
  146 +// dispatch_async(dispatch_get_main_queue(), ^{
  147 +// [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
  148 +//
  149 +// });
  150 +// NSString *urlStr = [[NSURL URLWithString:pathStr relativeToURL:_dataSessionManager.baseURL] absoluteString];
  151 +// NSString *methodStr = [self stringWithMethod:method];
  152 +// NSMutableURLRequest *request = [_dataSessionManager.requestSerializer requestWithMethod:methodStr URLString:urlStr parameters:parameters error:nil];
  153 +// __block NSURLSessionDataTask *task = nil;
  154 +// task = [_dataSessionManager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {//
  155 +// [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
  156 +// NSError *err = nil;
  157 +// id data = nil;
  158 +// if(error) {
  159 +// err = error;
  160 +// }else {
  161 +// NSDictionary *responseObjectDic = [responseObject mj_keyValues];
  162 +// NSString *resultCode = [NSString stringWithFormat:@"%@", responseObjectDic[errorCode]];
  163 +//
  164 +// if([resultCode isEqualToString:@"0"]) {
  165 +// data = responseObjectDic[requestData];
  166 +// } else {
  167 +// err = [[NSError alloc] initWithDomain:responseObjectDic[errorMessage] code:[resultCode integerValue] userInfo:nil];
  168 +// }
  169 +// }
  170 +// dispatch_async(dispatch_get_main_queue(), ^{
  171 +// completionHandler(data, err);
  172 +// });
  173 +//
  174 +// }];
  175 +// [task resume];
  176 +// return task;
  177 +//}
  178 +//
  179 +//- (NSString *)stringWithMethod:(HTTP_REQUEST_METHOD)method {
  180 +// switch (method) {
  181 +// case E_HTTP_REQUEST_METHOD_GET: return @"GET"; break;
  182 +// case E_HTTP_REQUEST_METHOD_POST: return @"POST"; break;
  183 +// default:
  184 +// break;
  185 +// }
  186 +// return @"";
  187 +//}
  188 +///** 清除所有任务 */
  189 +//- (void)cleanAllTask {
  190 +// [self invalidateManagers];
  191 +// [self initManagers];
  192 +//}
  193 +//
  194 +//- (void)invalidateManagers {
  195 +// [_dataSessionManager invalidateSessionCancelingTasks:YES];
  196 +//}
  197 +//
  198 +//#pragma mark -
  199 +//#pragma mark - Ptavite Methods
  200 +//- (void)initManagers {
  201 +//
  202 +// _dataSessionManager = [[AFHTTPSessionManager alloc] initWithBaseURL:nil];
  203 +// [_dataSessionManager setRequestSerializer:[AFHTTPRequestSerializer serializer]];
  204 +// [_dataSessionManager.requestSerializer setTimeoutInterval:kTimeoutInterval];
  205 +//// [_dataSessionManager setResponseSerializer:[AFJSONResponseSerializer serializer]];
  206 +//// _dataSessionManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html",@"image/jpeg",@"text/javascript",@"application/json",@"text/json",@"text/plain",nil];
  207 +// _dataSessionManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/html",@"text/json", @"text/javascript", nil];
  208 +//}
  209 +
  210 +@end
... ...
CNLiveUploadManager/util/UserInformationModel.h 0 → 100644
  1 +//
  2 +// UserInformationModel.h
  3 +// CNLive
  4 +//
  5 +// Created by Kim on 15/10/22.
  6 +// Copyright © 2015年 雷浩杰. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +#import <UIKit/UIKit.h>
  11 +@interface UserInformationModel : NSObject
  12 +
  13 +@property (nonatomic, copy) NSString *uid;//用户uId
  14 +@property (nonatomic, copy) NSString *gender;//性别
  15 +@property (nonatomic, copy) NSString *nickname;//昵称
  16 +@property (nonatomic, copy) NSString *location;//用户所在地的
  17 +@property (nonatomic, copy) NSString *faceUrl;//头像url
  18 +@property (nonatomic, copy) NSString *bigFaceUrl;//头像url 大图
  19 +@property (nonatomic, copy) NSString *token;//token
  20 +@property (nonatomic, copy) NSString *extInfo;//自定义信息
  21 +@property (nonatomic, copy) NSString *mobile;//手机号
  22 +@property (nonatomic, copy) NSString *email;//邮箱
  23 +@property (nonatomic ,copy) NSString *qqUid;//qqId
  24 +@property (nonatomic ,copy) NSString *hUid;//
  25 +@property (nonatomic ,copy) NSString *sinaUid;//新浪id
  26 +@property (nonatomic ,copy) NSString *wxUid;//微信id
  27 +@property (nonatomic ,copy) NSString *renrenUid;//人人id
  28 +@property (nonatomic ,assign) BOOL isNewUser;//是否第一次登录 是YES 否NO
  29 +@property (nonatomic ,copy) NSString *platformId;//渠道id
  30 +@property (nonatomic, copy) NSString *signature;//个性签名
  31 +@property (nonatomic ,assign) BOOL isDaren;//是否是达人 是YES 否NO
  32 +@property (nonatomic ,assign) BOOL isWitness;//是否是目击者 是YES 否NO
  33 +
  34 ++ (UserInformationModel *)manager;
  35 +
  36 +- (void)cleanUserInfo;
  37 +
  38 +@end
... ...
CNLiveUploadManager/util/UserInformationModel.m 0 → 100644
  1 +//
  2 +// UserInformationModel.m
  3 +// CNLive
  4 +//
  5 +// Created by Kim on 15/10/22.
  6 +// Copyright © 2015年 雷浩杰. All rights reserved.
  7 +//
  8 +
  9 +#import "UserInformationModel.h"
  10 +
  11 +@implementation UserInformationModel
  12 +
  13 ++ (UserInformationModel *)manager
  14 +{
  15 + static id instance = nil;
  16 + static dispatch_once_t onceToken;
  17 + dispatch_once(&onceToken, ^{
  18 + instance = [[self alloc] init];
  19 + });
  20 +//
  21 +// [instance mj_setKeyValues:[CNTools getLocalUserInfo]];
  22 +
  23 + return instance;
  24 +}
  25 +
  26 +- (NSString *)uid
  27 +{
  28 +// if ([CNTools isEmptyString:_uid]) {
  29 +// return @"0";
  30 +// }
  31 + return _uid;
  32 +}
  33 +
  34 +- (void)cleanUserInfo
  35 +{
  36 + self.uid = nil;
  37 + self.location = nil;
  38 + self.mobile = nil;
  39 + self.nickname = nil;
  40 + self.gender = nil;
  41 + self.email = nil;
  42 + self.faceUrl = nil;
  43 + self.token = nil;
  44 + self.extInfo = nil;
  45 + self.qqUid = nil;
  46 + self.hUid = nil;
  47 + self.sinaUid = nil;
  48 + self.wxUid = nil;
  49 + self.renrenUid = nil;
  50 + self.isNewUser = nil;
  51 + self.platformId = nil;
  52 + self.signature = nil;
  53 + self.isDaren = nil;
  54 + self.isWitness = nil;
  55 + self.bigFaceUrl = nil;
  56 +}
  57 +@end
... ...
CNLiveUploadManager/上传/CNLiveUploadManager.h 0 → 100755
  1 +//
  2 +// CNUploadManager.h
  3 +// CNLiveTestDemo
  4 +//
  5 +// Created by 梁星国 on 2018/9/19.
  6 +// Copyright © 2018年 梁星国. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +#import <UIKit/UIKit.h>
  11 +#import <PLShortVideoKit/PLShortVideoKit.h>
  12 +#import <Qiniu/QNResponseInfo.h>
  13 +#import "UIImage+zipData.h"
  14 +
  15 +@class CNLiveUploadModel;
  16 +
  17 +////////////////////////////////////////////////////////
  18 +//////////// 发送图片,视频限制
  19 +////////////////////////////////////////////////////////
  20 +#define kFriendsCircle_limit_photo 20*1024.0*1024.0 //朋友圈限制图片20M
  21 +#define kFirendsCircle_limit_video 30*1024.0*1024.0 //朋友圈限制视频30M
  22 +#define kTarentoComment_limit_photo 10*1024.0*1024.0 //达人评论10M
  23 +#define kSweepCode_limit_phoho 10*1024.0*1024.0 //扫码10M限制
  24 +#define kChat_limit_photo 20*1024.0*1024.0 //聊天限制图片20M
  25 +#define kChat_limit_video 20*1024.0*1024.0 //聊天限制视频20M
  26 +
  27 +#define kCNUploadSize10MB 10*1024*1024 //用于大于10MB的变为960*540分辨率
  28 +#define kCNUploadSize20MB 20*1024*1024 //用于大于20MB的变为960*540分辨率
  29 +#define kCNUploadSize30MB 30*1024*1024 //用于大于30MB的变为640*480分辨率
  30 +#define kCNUploadSize40MB 40*1024*1024 //用于大于40MB的变为640*480分辨率
  31 +#define kCNUploadSize50MB 50*1024*1024 //用于大于50MB的变为640*480分辨率
  32 +#define kCNUploadSize100MB 100*1024*1024 //用于大于100MB的变为640*480分辨率
  33 +
  34 +typedef NS_ENUM(NSUInteger, CNLiveUploadType) {
  35 + CNLiveUploadTypeQN, //七牛
  36 + CNLiveUploadTypeKS, //金山
  37 + CNLiveUploadTypeOther, //AFNetWorking
  38 +};
  39 +
  40 +typedef NS_ENUM(NSUInteger, AppPhototLimitType) {
  41 + AppPhototLimitTypeFriendsCircle = 0, //朋友圈图片限制20M
  42 + AppPhototLimitTypeTarentoComment = 1, //达人评论图片限制10M
  43 + AppPhototLimitTypeSweepCode = 2, //扫码图片限制10M
  44 + AppPhototLimitTypeChat = 3, //聊天图片限制20M
  45 +};
  46 +
  47 +
  48 +typedef void (^successBlock)(NSMutableArray* fileArray);//成功数组
  49 +typedef void (^failureBlock)(NSMutableArray* errorArray, NSError *error);//失败数组,错误
  50 +
  51 +typedef void (^successModelBlock)(CNLiveUploadModel *uploadModel);//成功model
  52 +typedef void (^failureModelBlock)(CNLiveUploadModel *uploadModel, NSError *error);//失败model,错误
  53 +
  54 +typedef void (^progressHandlerBlock)(float progress);//进度
  55 +
  56 +@interface CNLiveUploadManager : NSObject
  57 +
  58 +
  59 +/**
  60 + 释放单例
  61 + */
  62 ++(void)attempDealloc;
  63 +
  64 +/**
  65 + 实例化
  66 + */
  67 ++(CNLiveUploadManager *)shareInsance;
  68 +
  69 +#pragma mark - 图片部分
  70 +
  71 +/**
  72 + 单张图片Data
  73 + *** 注意:传入参数dataArray先进行PHAsset,ALAsset取图片压缩,防止内存崩溃 ***
  74 + @param type 上传方式
  75 + @param token token
  76 + @param data 图片data
  77 + @param progress 上传进度
  78 + @param success 成功回调
  79 + @param failure 失败回调
  80 + */
  81 ++ (void)uploadType:(CNLiveUploadType)type token:(NSString*)token data:(NSData *)data progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure;
  82 +
  83 +/**
  84 + 单张上传(含压缩)
  85 + *** 注意:无限制直接压缩上传 ***
  86 + @param type 上传方式
  87 + @param token token
  88 + @param image image
  89 + @param progress 上传进度
  90 + @param success 成功回调
  91 + @param failure 失败回调
  92 + */
  93 ++ (void)uploadType:(CNLiveUploadType)type token:(NSString*)token image:(UIImage *)image progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure;
  94 +
  95 +/**
  96 + PHAsset 和 ALAsset(不在适配) 上传 (无限制)
  97 +
  98 + @param type 上传方式
  99 + @param asset PHAsset 和 ALAsset
  100 + @param token token
  101 + @param progress 上传进度
  102 + @param success 成功回调
  103 + @param failure 失败回调
  104 + */
  105 ++ (void)uploadType:(CNLiveUploadType)type asset:(id)asset token:(NSString *)token progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure;
  106 +
  107 +/**
  108 + 多张上传(含压缩)
  109 + *** 注意:无限制直接压缩上传 ***
  110 + @param type 上传方式
  111 + @param token token
  112 + @param imageArr 上传图片
  113 + @param progress 上传进度
  114 + @param success 成功回调
  115 + @param failure 失败回调
  116 + */
  117 ++ (void)uploadType:(CNLiveUploadType)type token:(NSString*)token imageArray:(NSMutableArray<UIImage *> *)imageArr progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure;
  118 +
  119 +/**
  120 + 多张上传(不含压缩)
  121 + *** 注意:传入参数dataArray先进行PHAsset,ALAsset取图片压缩,防止内存崩溃 ***
  122 + @param type 上传方式
  123 + @param token token
  124 + @param dataArray 上传图片NSData
  125 + @param progress 上传进度
  126 + @param success 成功回调
  127 + @param failure 失败回调
  128 + */
  129 ++ (void)uploadType:(CNLiveUploadType)type token:(NSString*)token dataArray:(NSMutableArray<NSData *> *)dataArray progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure;
  130 +
  131 +#pragma mark - 视频部分
  132 +
  133 +/**
  134 + 上传你视频
  135 +
  136 + @param type 上传方式
  137 + @param file 路径
  138 + @param token token
  139 + @param progress 进度
  140 + @param success 成功回调
  141 + @param failure 失败回调
  142 + */
  143 ++ (void)uploadVideoType:(CNLiveUploadType)type file:(NSString *)file token:(NSString *)token progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure;
  144 +
  145 +#pragma mark - /** 业务部分 **/
  146 +
  147 +/// 单图上传 (asset取得Image - 压缩或原图 - 限制 - 筛选)
  148 ++ (void)uploadLimitType:(CNLiveUploadType)type asset:(id)asset isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType token:(NSString *)token progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure;
  149 +
  150 +/// 单图上传 (Image - 压缩或原图 - 限制 - 筛选)
  151 +
  152 ++ (void)uploadLimitType:(CNLiveUploadType)type image:(UIImage *)image isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType token:(NSString *)token progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure;
  153 +
  154 +
  155 +/// 多张图上传 (images - 压缩或原图 - 限制 - 筛选)
  156 ++ (void)uploadLimitType:(CNLiveUploadType)type imageArray:(NSMutableArray *)imageArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType token:(NSString *)token progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure;
  157 +
  158 +/// 多张图上传 (assetArray - 压缩 - 限制 - 筛选)
  159 ++ (void)uploadLimitType:(CNLiveUploadType)type token:(NSString *)token assetArray:(NSMutableArray *)assetArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure;
  160 +
  161 +
  162 +/// 单个视频上传 (video - 压缩 - 限制 - 筛选)
  163 ++ (void)uploadLimitVideoType:(CNLiveUploadType)type token:(NSString *)token asset:(id)asset outputPath:(NSString *)outputPath progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure;
  164 +
  165 +#pragma mark - 请求token 上传
  166 +/// 请求token 单张上传 (asset - 压缩 - 限制 - 筛选)
  167 ++ (void)uploadRequestType:(CNLiveUploadType)type url:(NSString *)url dic:(NSDictionary *)dic asset:(id)asset isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure;
  168 +
  169 +/// 请求token 单图上传 (Image - 压缩或原图 - 限制 - 筛选)
  170 ++ (void)uploadRequestType:(CNLiveUploadType)type url:(NSString *)url dic:(NSDictionary *)dic image:(UIImage *)image isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure;
  171 +
  172 +/// 请求token 多张图上传 (images - 压缩或原图 - 限制 - 筛选)
  173 ++ (void)uploadRequestType:(CNLiveUploadType)type url:(NSString *)url dic:(NSDictionary *)dic imageArray:(NSMutableArray *)imageArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure;
  174 +
  175 +
  176 +/// 请求token (assetArray - 压缩 - 限制 - 筛选)
  177 ++ (void)uploadRequestType:(CNLiveUploadType)type url:(NSString *)url dic:(NSDictionary *)dic assetArray:(NSMutableArray *)assetArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure;
  178 +
  179 +/// 请求token 单个视频上传 (video - 系统压缩 - 限制 - 筛选)
  180 ++ (void)uploadRequestVideoType:(CNLiveUploadType)type url:(NSString *)url dic:(NSDictionary *)dic asset:(id)asset outputPath:(NSString *)outputPath progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure;
  181 +
  182 +/// 请求token 单个视频上传 (video - 七牛短视频压缩 - 限制 - 筛选)
  183 ++ (void)uploadRequestWhithPLShortVideoType:(CNLiveUploadType)type outputPath:(NSString *)outputPath url:(NSString *)url dic:(NSDictionary *)dic asset:(id)asset limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure;
  184 +
  185 +
  186 +#pragma mark - 处理方法
  187 +
  188 +///筛选 是否视频在限制内
  189 ++ (BOOL)isVideoLimitType:(AppPhototLimitType)limitType data:(NSData *)data;
  190 +
  191 +/// 筛选 是否图片在限制内
  192 ++ (BOOL)isImageLimitType:(AppPhototLimitType)limitType data:(NSData *)data;
  193 +
  194 +
  195 +#pragma mark - 七牛短视频处理方法
  196 +
  197 +/// 根据限制获取视频分辨率
  198 ++ (PLSFilePreset)presetWithVideoLimitType:(AppPhototLimitType)limitType url:(NSURL *)url dataL:(float)dataL;
  199 +
  200 +///根据分辨力设置码率
  201 ++ (float)bitrateWithPreset:(PLSFilePreset)perset avAsset:(AVAsset *)avAsset url:(NSURL *)url dataL:(float)dataL;
  202 +
  203 +/**
  204 + 短视频分辨率压缩导出
  205 +
  206 + @param asset asset
  207 + @param outputPath 导出路径
  208 + @param limitType 根据限制来判断进入设置码率和分辨率
  209 + @param success 成功
  210 + @param progressCount 进度
  211 + @param failure 是啊比
  212 + */
  213 ++ (void)zipVideoWithAsset:(id) asset outputPath:(NSString *)outputPath limitType:(AppPhototLimitType)limitType success:(void(^)(NSURL * url))success progressCount:(void(^)(float progress)) progressCount failure:(void(^)(void))failure;
  214 +
  215 +
  216 +
  217 +@end
  218 +
  219 +
  220 +#pragma mark - CNLiveUploadModel
  221 +
  222 +@interface CNLiveUploadModel : NSObject
  223 +/** 状态码 */
  224 +@property (copy, nonatomic) NSString *code;
  225 +/** 索引 */
  226 +@property (assign, nonatomic) NSInteger index;
  227 +/** 图片路径 (视频,图片) 封装只返回key */
  228 +@property (copy, nonatomic) NSString *imageUrl;
  229 +/** file */
  230 +@property (copy, nonatomic) NSString *file;
  231 +/** 消息 */
  232 +@property (copy, nonatomic) NSString *message;
  233 +/** 图片 */
  234 +@property (strong, nonatomic) UIImage *image;
  235 +/** imageW */
  236 +@property (assign, nonatomic) NSInteger imageW;
  237 +/** imageH */
  238 +@property (assign, nonatomic) NSInteger imageH;
  239 +/** CNAsset */
  240 +@property (strong, nonatomic) id asset;
  241 +
  242 +// 七牛回调参数 QNResponseInfo
  243 +
  244 +@property (strong, nonatomic) id info;
  245 +
  246 +@property (copy, nonatomic) NSString *key;
  247 +
  248 +@property (copy, nonatomic) NSDictionary *resp;
  249 +
  250 +// 服务器参数
  251 +@property (strong, nonatomic) id responseObject;
  252 +
  253 +@end
  254 +
... ...
CNLiveUploadManager/上传/CNLiveUploadManager.m 0 → 100644
  1 +//
  2 +// CNUploadManager.m
  3 +// CNLiveTestDemo
  4 +//
  5 +// Created by 梁星国 on 2018/9/19.
  6 +// Copyright © 2018年 梁星国. All rights reserved.
  7 +//
  8 +
  9 +#import "CNLiveUploadManager.h"
  10 +//#import "CNImagePickerController.h"
  11 +#import <AssetsLibrary/AssetsLibrary.h>
  12 +#import <Qiniu/QiniuSDK.h>
  13 +#import <Qiniu/QNUploadManager.h>
  14 +#import <Photos/Photos.h>
  15 +#import <HappyDNS/HappyDNS.h>
  16 +#import <AFNetworking/AFNetworking.h>
  17 +#import "PHAsset+zipData.h"
  18 +#import "HttpService.h"
  19 +
  20 +#import "CNTools.h"
  21 +#import "UserInformationModel.h"
  22 +
  23 +//
  24 +//#pragma mark - 七牛category
  25 +
  26 +@implementation NSData(Qiniu)
  27 +
  28 +//获取图片格式
  29 +- (NSString *) imageFormatType{
  30 + uint8_t c;
  31 + [self getBytes:&c length:1];
  32 + switch (c) {
  33 + case 0xFF: return @".jpeg";
  34 + case 0x89: return @".png";
  35 + case 0x47: return @".gif";
  36 + case 0x49:
  37 + case 0x4D: return @".tiff";
  38 + default: return @".jpeg";
  39 + }
  40 + return nil;
  41 +}
  42 +
  43 +@end
  44 +
  45 +@implementation NSString(Qiniu)
  46 +/**
  47 + * 字符串判空
  48 + *
  49 + * @param string 需要判空的自字符串
  50 + * @return BOOL类型,YES为空字符
  51 + *
  52 + */
  53 ++ (BOOL)isEmpty:(NSString *)string {
  54 + return [string isEqual:[NSNull null]] || string == nil || string.length == 0;
  55 +}
  56 +
  57 +/**
  58 + 视频BucketKey,BucketKey为文件路径
  59 + */
  60 ++ (NSString *)getBucketKeyFromServerWithExt:(NSString *)ext
  61 +{
  62 + // @"82/wjj/video/TestUserUpload/2018/02/02/151754170779417093932.mp4"
  63 + NSString *spid = [CNTools getSpid];
  64 + NSString *spBucketKey = [NSString stringWithFormat:@"%@/wjj/video",spid];
  65 + NSString *darenId = [UserInformationModel manager].uid;
  66 + NSString *yearTime = [CNTools getyyMMdd];//@"2018/02/02";//tools
  67 + NSString *timestampStr = [CNTools get13tsRandTimeStr];//@"151754170779417093932";//tools time+8rand
  68 + // NSString *ext = @"mp4";//mp4
  69 + NSString *bucketKey = [NSString stringWithFormat:@"%@/%@/%@/%@.%@",spBucketKey,darenId,yearTime,timestampStr,ext];
  70 + NSLog(@"bucketKey:%@",bucketKey);
  71 + return bucketKey;
  72 +}
  73 +
  74 +
  75 +/**
  76 + 图片的BucketKey,BuketKey为文件路径
  77 + */
  78 ++ (NSString *)getImageBuketkeyFromServerWithExt:(NSString *)ext{
  79 + NSString *spid = [CNTools getSpid];
  80 + NSString *imgBucketKey = [NSString stringWithFormat:@"%@/img", spid];
  81 + NSString *yearTime = [CNTools getyyMMdd];
  82 + NSString *timeTampStr = [CNTools get13tsRandTimeStr];
  83 + NSString *bucketKey = [NSString stringWithFormat:@"%@/%@/%@%@",imgBucketKey,yearTime,timeTampStr,ext];
  84 + return bucketKey;
  85 +}
  86 +
  87 +
  88 +@end
  89 +
  90 +@implementation NSDictionary(Qiniu)
  91 +
  92 +- (BOOL)containsObjectForKey:(id)key {
  93 + if (!key) return NO;
  94 + return self[key] != nil;
  95 +}
  96 +
  97 +@end
  98 +//
  99 +//
  100 +//@implementation PHAsset (Qiniu)
  101 +
  102 +//- (UIImage *)imageURL:(PHAsset *)phAsset targetSize:(CGSize)targetSize {
  103 +// __block UIImage *image = nil;
  104 +//
  105 +// PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
  106 +// options.networkAccessAllowed = YES;
  107 +// options.synchronous = YES;
  108 +//
  109 +// // 设置 resizeMode = PHImageRequestOptionsResizeModeExact, 否则返回的图片大小不一定是设置的 targetSize
  110 +// options.resizeMode = PHImageRequestOptionsResizeModeExact;
  111 +//
  112 +// // 设置 deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat,是保证 resultHandler 值回调一次,否则可能回回调多次,只有最后一次返回的图片大小等于设置的 targetSize
  113 +// options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
  114 +//
  115 +// PHImageManager *manager = [PHImageManager defaultManager];
  116 +// [manager requestImageForAsset:phAsset targetSize:targetSize contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
  117 +// image = result;
  118 +// }];
  119 +//
  120 +// return image;
  121 +//}
  122 +//
  123 +//
  124 +//- (NSURL *)getImageFilePath {
  125 +//
  126 +// NSString *cacheFolder = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
  127 +// NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
  128 +// formatter.dateFormat = @"yyyyMMddHHmmssSSS";
  129 +// NSString *nowTimeStr = [formatter stringFromDate:[NSDate dateWithTimeIntervalSinceNow:0]];
  130 +// NSString *urlString = [NSString stringWithFormat:@"%@/%@.JPG", cacheFolder, nowTimeStr];
  131 +// return [NSURL fileURLWithPath:urlString];
  132 +//
  133 +//}
  134 +
  135 +//- (NSURL *)getImageURL:(PHAsset *)phAsset {
  136 +//
  137 +// PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
  138 +// options.networkAccessAllowed = YES;
  139 +// options.synchronous = YES;
  140 +//
  141 +// PHImageManager *manager = [PHImageManager defaultManager];
  142 +// __block NSURL *url = nil;
  143 +// __weak typeof(self) wself = self;
  144 +// [manager requestImageDataForAsset:phAsset options:options resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
  145 +// if (imageData) {
  146 +// // 这里需要重新将图片数据写到 App 可以访问的目录,不然直接使用 info 中的 url,可能会获取不到图片数据
  147 +// url = [wself getImageFilePath];
  148 +// [[NSFileManager defaultManager] createFileAtPath:url.path contents:imageData attributes:nil];
  149 +// }
  150 +// }];
  151 +//
  152 +// return url;
  153 +//}
  154 +
  155 +#pragma mark - 导出部分
  156 +//- (NSURL *)movieURL {
  157 +// __block NSURL *url = nil;
  158 +//
  159 +// dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
  160 +//
  161 +// if (self.mediaType == PHAssetMediaTypeVideo) {
  162 +// PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
  163 +// options.version = PHVideoRequestOptionsVersionOriginal;
  164 +// options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
  165 +// options.networkAccessAllowed = YES;
  166 +//
  167 +// PHImageManager *manager = [PHImageManager defaultManager];
  168 +// [manager requestAVAssetForVideo:self options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
  169 +// AVURLAsset *urlAsset = (AVURLAsset *)asset;
  170 +// url = urlAsset.URL;
  171 +//
  172 +// dispatch_semaphore_signal(semaphore);
  173 +// }];
  174 +// }
  175 +//
  176 +// dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
  177 +//
  178 +// return url;
  179 +//}
  180 +//
  181 +//
  182 +//@end
  183 +//
  184 +//
  185 +
  186 +#pragma mark - CNLiveUploadManager
  187 +
  188 +@interface CNLiveUploadManager ()
  189 +
  190 +@property (nonatomic, strong) QNUploadManager *qnUploadManager;
  191 +
  192 +
  193 +@end
  194 +
  195 +@implementation CNLiveUploadManager
  196 +
  197 +static CNLiveUploadManager *_uploadManager;
  198 +/// 实例化
  199 ++(CNLiveUploadManager *)shareInsance{
  200 + static dispatch_once_t onceToken;
  201 + dispatch_once(&onceToken, ^{
  202 + _uploadManager = [[CNLiveUploadManager alloc] init];
  203 + });
  204 + return _uploadManager;
  205 +}
  206 +
  207 +/// 初始化
  208 +- (instancetype)init {
  209 + self = [super init];
  210 + if (self) {
  211 + // 配置信息
  212 + QNConfiguration *config = [QNConfiguration build:^(QNConfigurationBuilder *builder) {
  213 + builder.useHttps = YES;
  214 + //设置断点续传
  215 + NSError *error;
  216 + builder.recorder = [QNFileRecorder fileRecorderWithFolder:@"网++" error:&error];
  217 + }];
  218 + _qnUploadManager = [[QNUploadManager alloc] initWithConfiguration:config];
  219 +
  220 + }
  221 + return self;
  222 +}
  223 +
  224 +/// 释放
  225 ++(void)attempDealloc {
  226 + if (_uploadManager) {
  227 + _uploadManager = nil;
  228 + }
  229 +
  230 +}
  231 +
  232 +#pragma mark - 基础上传一层
  233 +/// 单张上传 - NSData
  234 +- (void)qnUploadWithToken:( NSString* )token data:(NSData * _Nonnull)data key:(NSString *)key progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  235 +
  236 + //上传
  237 + NSString *total = [NSString stringWithFormat:@"1"];
  238 + NSString *current = [NSString stringWithFormat:@"1"];
  239 + NSDictionary *dic = @{
  240 + @"x:total":total,
  241 + @"x:current":current
  242 + }.copy;
  243 +
  244 + QNUploadOption *opt = [[QNUploadOption alloc] initWithMime:nil progressHandler:^(NSString *key, float percent) {
  245 +
  246 + !progress ? : progress(percent);
  247 + } params:dic checkCrc:YES cancellationSignal:nil];
  248 +
  249 + [_qnUploadManager putData:data key:key token:token complete:^(QNResponseInfo *info, NSString *key, NSDictionary *resp) {
  250 +
  251 + dispatch_async(dispatch_get_main_queue(), ^{
  252 +
  253 + //返回结果
  254 + if (info.ok) {//成功
  255 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  256 + uploadModel.info = info;
  257 + uploadModel.key = key;
  258 + uploadModel.resp = resp;
  259 +
  260 + uploadModel.code = @"200";
  261 + uploadModel.index = 1;
  262 + uploadModel.imageUrl = key;
  263 + uploadModel.message = @"上传成功";
  264 + uploadModel.image = [UIImage imageWithData:data];
  265 + uploadModel.imageW = uploadModel.image.size.width;
  266 + uploadModel.imageH = uploadModel.image.size.height;
  267 +
  268 + !success ? : success(uploadModel);
  269 +
  270 + }else{//失败
  271 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  272 + uploadModel.info = info;
  273 + uploadModel.key = key;
  274 + uploadModel.resp = resp;
  275 +
  276 + uploadModel.code = @"400";
  277 + uploadModel.index = 1;
  278 + uploadModel.imageUrl = @"";
  279 + uploadModel.message = @"上传失败";
  280 + uploadModel.image = [UIImage imageWithData:data];
  281 + uploadModel.imageW = uploadModel.image.size.width;
  282 + uploadModel.imageH = uploadModel.image.size.height;
  283 +
  284 + !failure ? : failure(uploadModel,info.error);
  285 + }
  286 + });
  287 +
  288 + } option:opt];
  289 +
  290 +}
  291 +
  292 +///单PHAsset上传 - PHAsset
  293 +- (void)qnUploadWithToken:(NSString*)token phAsset:(PHAsset *)phAsset key:(NSString *)key progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  294 +
  295 + //上传
  296 + NSString *total = [NSString stringWithFormat:@"1"];
  297 + NSString *current = [NSString stringWithFormat:@"1"];
  298 + NSDictionary *dic = @{
  299 + @"x:total":total,
  300 + @"x:current":current
  301 + }.copy;
  302 + __block CGFloat currentPresent =0;//当前进度
  303 + QNUploadOption *opt = [[QNUploadOption alloc] initWithMime:nil progressHandler:^(NSString *key, float percent) {
  304 + currentPresent += percent;
  305 + NSLog(@"输出个数%f",currentPresent);//单个视频的进度
  306 + !progress ? : progress(currentPresent);
  307 + } params:dic checkCrc:YES cancellationSignal:nil];
  308 +
  309 + [_qnUploadManager putPHAsset:phAsset key:key token:token complete:^(QNResponseInfo *info, NSString *key, NSDictionary *resp) {
  310 + dispatch_async(dispatch_get_main_queue(), ^{
  311 + //返回结果
  312 + if (info.ok) {//成功
  313 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  314 + uploadModel.info = info;
  315 + uploadModel.key = key;
  316 + uploadModel.resp = resp;
  317 +
  318 + uploadModel.code = @"200";
  319 + uploadModel.index = 1;
  320 + uploadModel.asset = phAsset;
  321 + uploadModel.imageUrl = key;
  322 + uploadModel.message = @"上传成功";
  323 +
  324 + !success ? : success(uploadModel);
  325 +
  326 + }else{//失败
  327 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  328 + uploadModel.info = info;
  329 + uploadModel.key = key;
  330 + uploadModel.resp = resp;
  331 +
  332 + uploadModel.code = @"103";
  333 + uploadModel.index = 1;
  334 + uploadModel.imageUrl = @"";
  335 + uploadModel.message = @"上传失败";
  336 +
  337 + !failure ? : failure(uploadModel,info.error);
  338 +
  339 + }
  340 + });
  341 +
  342 + } option:opt];
  343 +
  344 +}
  345 +
  346 +/// (视频)单file上传 - file
  347 +- (void)qnUploadVideoWithToken:(NSString*)token file:(NSString *)file key:(NSString *)key progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  348 + //上传
  349 + NSString *total = [NSString stringWithFormat:@"1"];
  350 + NSString *current = [NSString stringWithFormat:@"1"];
  351 + NSDictionary *dic = @{
  352 + @"x:total":total,
  353 + @"x:current":current
  354 + }.copy;
  355 +
  356 + QNUploadOption *opt = [[QNUploadOption alloc] initWithMime:nil progressHandler:^(NSString *key, float percent) {
  357 +
  358 + NSLog(@"输出个数%f",percent);//单个视频的进度
  359 + !progress ? : progress(percent);
  360 + } params:dic checkCrc:YES cancellationSignal:nil];
  361 +
  362 + [_qnUploadManager putFile:file key:key token:token complete:^(QNResponseInfo *info, NSString *key, NSDictionary *resp) {
  363 + dispatch_async(dispatch_get_main_queue(), ^{
  364 + //返回结果
  365 + if (info.ok) {//成功
  366 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  367 + uploadModel.info = info;
  368 + uploadModel.key = key;
  369 + uploadModel.resp = resp;
  370 +
  371 + uploadModel.code = @"200";
  372 + uploadModel.index = 1;
  373 + uploadModel.file = file;
  374 + uploadModel.imageUrl = key;
  375 + uploadModel.file = file;
  376 + uploadModel.message = @"上传成功";
  377 +
  378 + !success ? : success(uploadModel);
  379 +
  380 + }else{//失败
  381 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  382 + uploadModel.info = info;
  383 + uploadModel.key = key;
  384 + uploadModel.resp = resp;
  385 +
  386 + uploadModel.code = @"400";
  387 + uploadModel.index = 1;
  388 + uploadModel.imageUrl = @"";
  389 + uploadModel.file = file;
  390 + uploadModel.message = @"上传失败";
  391 +
  392 + !failure ? : failure(uploadModel,info.error);
  393 + }
  394 + });
  395 +
  396 + } option:opt];
  397 +}
  398 +
  399 +
  400 +/// 多张上传 - NSData - 排序
  401 +- (void)qnUploadWithToken:(NSString*)token dataArray:(NSMutableArray<NSData *> *)dataArr keys:(NSMutableArray<NSString *>*)keys progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  402 +
  403 + //上传图片数组
  404 + if (dataArr.count != keys.count) {
  405 + NSError *error = [NSError errorWithDomain:@"图片数和路径数不等" code:102 userInfo:@{NSLocalizedDescriptionKey:@"图片数和路径数不等,请重新获取"}];
  406 + !failure ? : failure(nil,error);
  407 + return;
  408 + }
  409 +
  410 + //回调数组
  411 + NSMutableArray *fileArray = [NSMutableArray array];//成功数组 CNLiveUploadModel
  412 + NSMutableArray *errorArray = [NSMutableArray array];//失败数组 CNLiveUploadModel
  413 + __block float count = 0;//进度
  414 +
  415 + //获得全局并发队列
  416 + dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  417 + //创建group
  418 + dispatch_group_t group = dispatch_group_create();
  419 + //GCD遍历图片数组
  420 + __weak __typeof(_qnUploadManager)weakManager = _qnUploadManager;
  421 + dispatch_apply(dataArr.count, globalQueue, ^(size_t index) {
  422 + dispatch_group_enter(group);
  423 + __strong __typeof(weakManager)strongManager = weakManager;
  424 +
  425 + //上传
  426 + NSString *total = [NSString stringWithFormat:@"%ld",(unsigned long)dataArr.count];
  427 + NSString *current = [NSString stringWithFormat:@"%ld",index+1];
  428 + NSDictionary *dic = @{
  429 + @"x:total":total,
  430 + @"x:current":current
  431 + }.copy;
  432 + QNUploadOption *opt = [[QNUploadOption alloc] initWithMime:nil progressHandler:^(NSString *key, float percent) {
  433 +
  434 + } params:dic checkCrc:YES cancellationSignal:nil];
  435 +
  436 + [strongManager putData:dataArr[index] key:keys[index] token:token complete:^(QNResponseInfo *info, NSString *key, NSDictionary *resp) {
  437 +
  438 + NSLog(@"***输出第%zi图片***",index);
  439 + //进度
  440 + count ++;
  441 + float progressCount = count / dataArr.count;
  442 + !progress ? : progress(progressCount);
  443 +
  444 + //返回结果
  445 + if (info.ok) {//成功
  446 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  447 + uploadModel.info = info;
  448 + uploadModel.key = key;
  449 + uploadModel.resp = resp;
  450 +
  451 + uploadModel.code = @"200";
  452 + uploadModel.index = index;
  453 + uploadModel.imageUrl = key;
  454 + uploadModel.message = @"上传成功";
  455 + uploadModel.image = [UIImage imageWithData:dataArr[index]];
  456 + uploadModel.imageW = uploadModel.image.size.width;
  457 + uploadModel.imageH = uploadModel.image.size.height;
  458 + [fileArray addObject:uploadModel];
  459 +
  460 + }else{//失败
  461 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  462 + uploadModel.info = info;
  463 + uploadModel.key = key;
  464 + uploadModel.resp = resp;
  465 +
  466 + uploadModel.code = @"400";
  467 + uploadModel.index = index;
  468 + uploadModel.imageUrl = @"";
  469 + uploadModel.message = @"上传失败";
  470 + uploadModel.image = [UIImage imageWithData:dataArr[index]];
  471 + uploadModel.imageW = uploadModel.image.size.width;
  472 + uploadModel.imageH = uploadModel.image.size.height;
  473 + [errorArray addObject:uploadModel];
  474 +
  475 + }
  476 +
  477 + dispatch_group_leave(group);
  478 +
  479 + } option:opt];
  480 +
  481 + });
  482 +
  483 + //group内的任务完成通知
  484 + dispatch_group_notify(group, dispatch_get_main_queue(), ^{
  485 +
  486 + if (dataArr.count == fileArray.count) {
  487 + //排序
  488 + [fileArray sortUsingComparator:^NSComparisonResult(CNLiveUploadModel * _Nonnull obj1, CNLiveUploadModel * _Nonnull obj2) {
  489 + if (obj1.index > obj2.index)
  490 + {
  491 + return NSOrderedDescending;
  492 + }
  493 + else
  494 + {
  495 + return NSOrderedAscending;
  496 + }
  497 + }];
  498 + !success ? : success(fileArray);
  499 + }else{
  500 + !success ? : success(fileArray);
  501 + NSError *error = [NSError errorWithDomain:@"上传出现错误" code:400 userInfo:@{NSLocalizedDescriptionKey:@"上传出现错误,请重新上传失败图片"}];
  502 + !failure ? : failure(errorArray,error);
  503 + }
  504 +
  505 + });
  506 +
  507 +}
  508 +
  509 +#pragma mark - 简单上传二层 添加Key
  510 +/// 单张NSData上传 - Key
  511 +-(void)qnUploadWithToken:(NSString*)token data:(NSData *)data progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure{
  512 +
  513 + //初始化上传需要的参数
  514 + //imageKey获取x
  515 + NSString *key = [NSString getImageBuketkeyFromServerWithExt:[data imageFormatType]];
  516 +
  517 + [self qnUploadWithToken:token data:data key:key progress:progress success:success failure:failure];
  518 +
  519 +}
  520 +
  521 +/// 单张上传 - Key - 压缩
  522 +-(void)qnUploadWithToken:(NSString*)token image:(UIImage *)image progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure{
  523 +
  524 + //初始化上传需要的参数
  525 + //imageData转换,压缩
  526 + NSData *data = [UIImage zipNSDataAndScaleWithImage:image];
  527 + //imageKey获取
  528 + NSString *key = [NSString getImageBuketkeyFromServerWithExt:[data imageFormatType]];
  529 +
  530 + [self qnUploadWithToken:token data:data key:key progress:progress success:success failure:failure];
  531 +
  532 +}
  533 +
  534 +
  535 +/// 单张PHAsset上传
  536 +- (void)qnUploadWithToken:(NSString*)token phAsset:(PHAsset *)phAsset progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  537 +
  538 +
  539 + //七牛token
  540 + if ([NSString isEmpty:token]) {
  541 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  542 + !failure ? : failure(nil,error);
  543 + return;
  544 + }
  545 +
  546 + //上传路径
  547 + if (phAsset) {
  548 + NSError *error = [NSError errorWithDomain:@"上传路径为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"上传为空,请重新获取"}];
  549 + !failure ? : failure(nil,error);
  550 + return;
  551 + }
  552 +
  553 + //初始化上传需要的参数
  554 + NSString *key = [NSString string];
  555 + if ([PHAsset getAssetType:phAsset] == CNAssetModelMediaTypePhotoGif) {
  556 + key = [NSString stringWithFormat:@"%@",[NSString getImageBuketkeyFromServerWithExt:@".gif"]];
  557 + }else{
  558 + key = [NSString stringWithFormat:@"%@",[NSString getImageBuketkeyFromServerWithExt:@".jpg"]];
  559 + }
  560 +
  561 + [self qnUploadWithToken:token phAsset:phAsset key:key progress:progress success:success failure:failure];
  562 +}
  563 +
  564 +/// 多张图片上传 - key - 压缩
  565 +- (void)qnUploadWithToken:(NSString*)token imageArray:(NSMutableArray<UIImage *> *)imageArr progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  566 +
  567 + //七牛token
  568 + if ([NSString isEmpty:token]) {
  569 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  570 + !failure ? : failure(nil,error);
  571 + return;
  572 + }
  573 +
  574 + //上传图片数组
  575 + if (imageArr.count <= 0) {
  576 + NSError *error = [NSError errorWithDomain:@"图片数组为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"图片数组为空,请重新获取"}];
  577 + !failure ? : failure(nil,error);
  578 + return;
  579 + }
  580 +
  581 + //初始化上传需要的参数
  582 + NSMutableArray *dataArray = @[].mutableCopy;
  583 + NSMutableArray *keyArray = @[].mutableCopy;
  584 + for (UIImage *image in imageArr) {
  585 + //imageData转换,压缩
  586 + NSData *data = [UIImage zipNSDataAndScaleWithImage:image];
  587 + [dataArray addObject:data];
  588 + //imageKey获取x
  589 + NSString *key = [NSString getImageBuketkeyFromServerWithExt:[data imageFormatType]];
  590 + [keyArray addObject:key];
  591 + }
  592 +
  593 + [self qnUploadWithToken:token dataArray:dataArray keys:keyArray progress:progress success:success failure:failure];
  594 +
  595 +}
  596 +
  597 +/// 多张图片dataArray上传 - Key
  598 +- (void)qnUploadWithToken:(NSString*)token dataArray:(NSMutableArray<NSData *> *)dataArray progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  599 +
  600 + //七牛token
  601 + if ([NSString isEmpty:token]) {
  602 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  603 + !failure ? : failure(nil,error);
  604 + return;
  605 + }
  606 +
  607 + //上传图片数组
  608 + if (dataArray.count <= 0) {
  609 + NSError *error = [NSError errorWithDomain:@"图片Data数组为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"图片Data数组为空,请重新获取"}];
  610 + !failure ? : failure(nil,error);
  611 + return;
  612 + }
  613 +
  614 + //初始化上传需要的参数
  615 + NSMutableArray *keyArray = @[].mutableCopy;
  616 + for (int i = 0; i < dataArray.count; i++) {
  617 +
  618 + NSString *key = [NSString getImageBuketkeyFromServerWithExt:[dataArray[i] imageFormatType]];
  619 + [keyArray addObject:key];
  620 + }
  621 +
  622 + [self qnUploadWithToken:token dataArray:dataArray keys:keyArray progress:progress success:success failure:failure];
  623 +
  624 +}
  625 +
  626 +
  627 +/// 视频路径上传 - key
  628 +- (void)qnUploadVideoWithToken:(NSString*)token file:(NSString *)file progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  629 +
  630 + //七牛token
  631 + if ([NSString isEmpty:token]) {
  632 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  633 + !failure ? : failure(nil,error);
  634 + return;
  635 + }
  636 +
  637 + //上传路径
  638 + if ([NSString isEmpty:file]) {
  639 +
  640 + NSError *error = [NSError errorWithDomain:@"上传路径为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"上传路径为空,请重新获取"}];
  641 + !failure ? : failure(nil,error);
  642 + return;
  643 +
  644 + }
  645 +
  646 + //初始化上传需要的参数
  647 + NSArray *extArr = [file componentsSeparatedByString:@"."];
  648 + NSString *key = [NSString getBucketKeyFromServerWithExt:[extArr lastObject]];
  649 +
  650 + [self qnUploadVideoWithToken:token file:file key:key progress:progress success:success failure:failure];
  651 +}
  652 +
  653 +
  654 +#pragma mark - 简单上传三层
  655 +/// 单张上传NSData
  656 ++ (void)uploadType:(CNLiveUploadType)type token:(NSString*)token data:(NSData *)data progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  657 + if (type == CNLiveUploadTypeQN) { //七牛上传
  658 + [[CNLiveUploadManager shareInsance]qnUploadWithToken:token data:data progress:progress success:success failure:failure];
  659 + }else if (type == CNLiveUploadTypeKS) {
  660 +
  661 + }else{
  662 +
  663 + }
  664 +}
  665 +
  666 +///单张上传UIImage
  667 ++ (void)uploadType:(CNLiveUploadType)type token:(NSString*)token image:(UIImage *)image progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  668 +
  669 + if (type == CNLiveUploadTypeQN) { //七牛上传
  670 + [[CNLiveUploadManager shareInsance]qnUploadWithToken:token image:image progress:progress success:success failure:failure];
  671 + }else if (type == CNLiveUploadTypeKS) {
  672 +
  673 + }else{
  674 +
  675 + }
  676 +}
  677 +
  678 +/// PHAsset 上传
  679 ++ (void)uploadType:(CNLiveUploadType)type asset:(id)asset token:(NSString *)token progress:(progressHandlerBlock)progress success:(successModelBlock) success failure:(failureModelBlock)failure{
  680 +
  681 + if (type == CNLiveUploadTypeQN) { //七牛上传
  682 +
  683 + if ([asset isKindOfClass:[PHAsset class]]) {
  684 +
  685 + [[CNLiveUploadManager shareInsance]qnUploadWithToken:token phAsset:(PHAsset *)asset progress:progress success:success failure:failure];
  686 + }
  687 +
  688 + }else if (type == CNLiveUploadTypeKS) {
  689 +
  690 + }else{
  691 +
  692 + }
  693 +
  694 +}
  695 +
  696 +/// CNLive上传多张图片
  697 ++ (void)uploadType:(CNLiveUploadType)type token:(NSString*)token imageArray:(NSMutableArray<UIImage *> *)imageArr progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  698 + if (type == CNLiveUploadTypeQN) { //七牛上传
  699 + [[CNLiveUploadManager shareInsance]qnUploadWithToken:token imageArray:imageArr progress:progress success:success failure:failure];
  700 + }else if (type == CNLiveUploadTypeKS) {
  701 +
  702 + }else{
  703 +
  704 + }
  705 +}
  706 +
  707 +/// CNLive上传多张NSData
  708 ++ (void)uploadType:(CNLiveUploadType)type token:(NSString*)token dataArray:(NSMutableArray<NSData *> *)dataArray progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  709 +
  710 + if (type == CNLiveUploadTypeQN) { //七牛上传
  711 + [[CNLiveUploadManager shareInsance]qnUploadWithToken:token dataArray:dataArray progress:progress success:success failure:failure];
  712 + }else if (type == CNLiveUploadTypeKS) {
  713 +
  714 + }else{
  715 +
  716 + }
  717 +
  718 +}
  719 +
  720 +/// (视频)路径上传
  721 ++ (void)uploadVideoType:(CNLiveUploadType)type file:(NSString *)file token:(NSString *)token progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  722 +
  723 + if (type == CNLiveUploadTypeQN) { //七牛上传
  724 + [[CNLiveUploadManager shareInsance]qnUploadVideoWithToken:token file:file progress:progress success:success failure:failure];
  725 + }else if (type == CNLiveUploadTypeKS) {
  726 +
  727 + }else{
  728 +
  729 + }
  730 +
  731 +}
  732 +
  733 +#pragma mark - /** 业务部分 **/
  734 +#pragma mark -- 七牛
  735 +///单张asset - asset取得Image - 压缩或原图 - 限制 - 筛选 实现
  736 +- (void)qnUploadLimitWithToken:(NSString*)token asset:(id)asset isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  737 +
  738 + //七牛token
  739 + if ([NSString isEmpty:token]) {
  740 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  741 + !failure ? : failure(nil,error);
  742 + return;
  743 + }
  744 +
  745 + //上传路径
  746 + if (!asset) {
  747 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  748 + !failure ? : failure(nil,error);
  749 + return;
  750 + }
  751 +
  752 + //压缩
  753 + [PHAsset outputImageAsset:asset isOriginal:isOriginal success:^(NSData *data) {
  754 + //去空
  755 + if (!data) {
  756 + NSError *error = [NSError errorWithDomain:@"图片转码失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"图片转码失败,请重新获取"}];
  757 + !failure ? : failure(nil,error);
  758 + return;
  759 + }
  760 +
  761 + //筛选
  762 + if ([CNLiveUploadManager isImageLimitType:limitType data:data]) {
  763 + [self qnUploadWithToken:token data:data progress:progress success:success failure:failure];
  764 + }else {
  765 + NSError *error = [NSError errorWithDomain:@"图片过大" code:104 userInfo:@{NSLocalizedDescriptionKey:@"图片过大,请重新获取"}];
  766 + !failure ? : failure(nil,error);
  767 + return;
  768 + }
  769 +
  770 + } failure:^{
  771 +
  772 + NSError *error = [NSError errorWithDomain:@"图片转码失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"图片转码失败,请重新获取"}];
  773 + !failure ? : failure(nil,error);
  774 + return;
  775 +
  776 + }];
  777 +
  778 +}
  779 +
  780 +///单张phasset - asset取得Image - 压缩或原图 - 限制 - 筛选 实现
  781 +- (void)qnUploadLimitWithToken:(NSString*)token phAsset:(PHAsset *)phAsset isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  782 +
  783 + //七牛token
  784 + if ([NSString isEmpty:token]) {
  785 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  786 + !failure ? : failure(nil,error);
  787 + return;
  788 + }
  789 +
  790 + //上传路径
  791 + if (!phAsset) {
  792 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  793 + !failure ? : failure(nil,error);
  794 + return;
  795 + }
  796 +
  797 + //压缩
  798 + [PHAsset outputImageAsset:phAsset isOriginal:isOriginal success:^(NSData *data) {
  799 + //去空
  800 + if (!data) {
  801 + NSError *error = [NSError errorWithDomain:@"图片转码失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"图片转码失败,请重新获取"}];
  802 + !failure ? : failure(nil,error);
  803 + return;
  804 + }
  805 +
  806 + //筛选
  807 + if ([CNLiveUploadManager isImageLimitType:limitType data:data]) {
  808 + [self qnUploadWithToken:token data:data progress:progress success:success failure:failure];
  809 + }else {
  810 + NSError *error = [NSError errorWithDomain:@"图片过大" code:104 userInfo:@{NSLocalizedDescriptionKey:@"图片过大,请重新获取"}];
  811 + !failure ? : failure(nil,error);
  812 + return;
  813 + }
  814 +
  815 + } failure:^{
  816 +
  817 + NSError *error = [NSError errorWithDomain:@"图片转码失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"图片转码失败,请重新获取"}];
  818 + !failure ? : failure(nil,error);
  819 + return;
  820 +
  821 + }];
  822 +
  823 +}
  824 +
  825 +
  826 +
  827 +///单张image - Image - 压缩或原图 - 限制 - 筛选) 实现
  828 +- (void)qnUploadLimitWithToken:(NSString*)token image:(UIImage *)image isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  829 +
  830 + //七牛token
  831 + if ([NSString isEmpty:token]) {
  832 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  833 + !failure ? : failure(nil,error);
  834 + return;
  835 + }
  836 +
  837 + //上传路径
  838 + if (!image) {
  839 + NSError *error = [NSError errorWithDomain:@"图片为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"图片为空,请重新获取"}];
  840 + !failure ? : failure(nil,error);
  841 + return;
  842 + }
  843 +
  844 + UIImage *origionImg = image;
  845 + if (origionImg) {
  846 + NSData *data = nil;
  847 + if (isOriginal) {
  848 + if (UIImageJPEGRepresentation(origionImg, 1.0)) {
  849 + data = UIImageJPEGRepresentation(origionImg, 1.0);
  850 + }else {
  851 + data = UIImagePNGRepresentation(origionImg);
  852 + }
  853 + }else{
  854 + data = [UIImage zipNSDataAndScaleWithImage:origionImg];//压缩
  855 + }
  856 +
  857 + //去空
  858 + if (!data) {
  859 + NSError *error = [NSError errorWithDomain:@"图片为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"图片为空,请重新获取"}];
  860 + !failure ? : failure(nil,error);
  861 + return;
  862 + }
  863 +
  864 + //筛选
  865 + if ([CNLiveUploadManager isImageLimitType:limitType data:data]) {
  866 + [self qnUploadWithToken:token data:data progress:progress success:success failure:failure];
  867 + }else{
  868 + NSError *error = [NSError errorWithDomain:@"图片过大" code:104 userInfo:@{NSLocalizedDescriptionKey:@"图片过大,请重新获取"}];
  869 + !failure ? : failure(nil,error);
  870 + return;
  871 +
  872 + }
  873 +
  874 + }else{
  875 + NSError *error = [NSError errorWithDomain:@"图片转码失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"图片转码失败,请重新获取"}];
  876 + !failure ? : failure(nil,error);
  877 + return;
  878 + }
  879 +
  880 +}
  881 +
  882 +/// 多张Assets上传 - Images - 压缩或原图 - 限制 - 筛选
  883 +- (void)qnUploadLimitWithToken:(NSString*)token assetArray:(NSMutableArray *)assetArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  884 +
  885 + //七牛token
  886 + if ([NSString isEmpty:token]) {
  887 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  888 + !failure ? : failure(nil,error);
  889 + return;
  890 + }
  891 +
  892 + //上传路径
  893 + if (assetArray.count <= 0) {
  894 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  895 + !failure ? : failure(nil,error);
  896 + return;
  897 + }
  898 +
  899 + //回调数组
  900 + NSMutableArray *fileArray = [NSMutableArray array];//成功数组 CNLiveUploadModel
  901 + NSMutableArray *errorArray = [NSMutableArray array];//失败数组 CNLiveUploadModel
  902 + //获得全局并发队列
  903 + dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  904 + //创建group
  905 + dispatch_group_t group = dispatch_group_create();
  906 +
  907 + //GCD遍历图片数组
  908 + NSInteger count = assetArray.count;
  909 + //进度
  910 + __block NSInteger progressCount = 0;
  911 + __weak typeof(self) weakSelf = self;
  912 + dispatch_apply(count, globalQueue, ^(size_t index) {
  913 + __strong typeof(weakSelf) strongSelf = weakSelf;
  914 + progressCount ++;
  915 +
  916 + id asset = assetArray[index];
  917 + if (!asset) {
  918 +
  919 + !progressCount ? : progress(progressCount/assetArray.count);
  920 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  921 + !failure ? : failure(nil,error);
  922 + return;
  923 + }
  924 +
  925 + //压缩
  926 + dispatch_group_enter(group);
  927 + [PHAsset outputImageAsset:asset isOriginal:isOriginal success:^(NSData *data) {
  928 + //筛选
  929 + if ([CNLiveUploadManager isImageLimitType:limitType data:data]) {
  930 +
  931 + [strongSelf qnUploadWithToken:token data:data progress:progress success:^(CNLiveUploadModel *uploadModel) {
  932 + uploadModel.index = index;
  933 + [fileArray addObject:uploadModel];
  934 + !progressCount ? : progress(progressCount/assetArray.count);
  935 + dispatch_group_leave(group);
  936 + } failure:^(CNLiveUploadModel *uploadModel, NSError *error) {
  937 + uploadModel.index = index;
  938 + [errorArray addObject:uploadModel];
  939 + !progressCount ? : progress(progressCount/assetArray.count);
  940 + dispatch_group_leave(group);
  941 + }];
  942 + }else {
  943 + !progressCount ? : progress(progressCount/assetArray.count);
  944 + dispatch_group_leave(group);
  945 + }
  946 +
  947 + } failure:^{
  948 + !progressCount ? : progress(progressCount/assetArray.count);
  949 + dispatch_group_leave(group);
  950 +
  951 + }];
  952 +
  953 + });
  954 +
  955 + //group内的任务完成通知
  956 + dispatch_group_notify(group, dispatch_get_main_queue(), ^{
  957 +
  958 + if (assetArray.count == fileArray.count) {
  959 + //排序
  960 + [fileArray sortUsingComparator:^NSComparisonResult(CNLiveUploadModel * _Nonnull obj1, CNLiveUploadModel * _Nonnull obj2) {
  961 + if (obj1.index > obj2.index)
  962 + {
  963 + return NSOrderedDescending;
  964 + }
  965 + else
  966 + {
  967 + return NSOrderedAscending;
  968 + }
  969 + }];
  970 + !success ? : success(fileArray);
  971 + }else{
  972 + !success ? : success(fileArray);
  973 + NSError *error = [NSError errorWithDomain:@"上传出现错误" code:400 userInfo:@{NSLocalizedDescriptionKey:@"上传出现错误,请重新上传失败图片"}];
  974 + !failure ? : failure(errorArray,error);
  975 + }
  976 +
  977 + });
  978 +
  979 +}
  980 +
  981 +///多张ImageArray - Images - 压缩或原图 - 限制 - 筛选
  982 +- (void)qnUploadLimitWithToken:(NSString*)token imageArray:(NSMutableArray<UIImage *> *)imageArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  983 +
  984 + //七牛token
  985 + if ([NSString isEmpty:token]) {
  986 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  987 + !failure ? : failure(nil,error);
  988 + return;
  989 + }
  990 +
  991 + //上传路径
  992 + if (imageArray.count <= 0) {
  993 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  994 + !failure ? : failure(nil,error);
  995 + return;
  996 + }
  997 +
  998 + // 编辑
  999 + NSMutableArray *uploadDataArray = [NSMutableArray array];
  1000 + for (UIImage *image in imageArray) {
  1001 +
  1002 + UIImage *origionImg = image;
  1003 + if (origionImg) {
  1004 + NSData *data = nil;
  1005 + //压缩
  1006 + if (isOriginal) {
  1007 + if (UIImageJPEGRepresentation(origionImg, 1.0)) {
  1008 + data = UIImageJPEGRepresentation(origionImg, 1.0);
  1009 + }else {
  1010 + data = UIImagePNGRepresentation(origionImg);
  1011 + }
  1012 + }else{
  1013 + data = [UIImage zipNSDataAndScaleWithImage:origionImg];//压缩
  1014 + }
  1015 +
  1016 + //去空
  1017 + if (!data) {
  1018 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  1019 + !failure ? : failure(nil,error);
  1020 + continue;
  1021 + }
  1022 + // 筛选
  1023 + if ([CNLiveUploadManager isImageLimitType:limitType data:data]) {
  1024 + [uploadDataArray addObject:data];
  1025 + }else{
  1026 + NSError *error = [NSError errorWithDomain:@"数据过大" code:104 userInfo:@{NSLocalizedDescriptionKey:@"数据过大,请重新获取"}];
  1027 + !failure ? : failure(nil,error);
  1028 + }
  1029 +
  1030 + }
  1031 +
  1032 + }
  1033 +
  1034 + /// 上传DataArray
  1035 + [self qnUploadWithToken:token dataArray:uploadDataArray progress:progress success:success failure:failure];
  1036 +
  1037 +}
  1038 +
  1039 +///单个视频上传 - 压缩或原图 - 限制 - 筛选) 实现
  1040 +- (void)qnUploadVideoLimitWithToken:(NSString*)token asset:(id)asset outputPath:(NSString *)outputPath progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  1041 +
  1042 + //七牛token
  1043 + if ([NSString isEmpty:token]) {
  1044 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  1045 + !failure ? : failure(nil,error);
  1046 + return;
  1047 + }
  1048 +
  1049 + //上传路径
  1050 + if (!asset) {
  1051 + NSError *error = [NSError errorWithDomain:@"上传路径为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"上传为空,请重新获取"}];
  1052 + !failure ? : failure(nil,error);
  1053 + return;
  1054 + }
  1055 +
  1056 + __weak typeof(self) weakSelf = self;
  1057 + [PHAsset getVideoWithAsset:asset outputPath:outputPath presetName:AVAssetExportPreset960x540 success:^(NSString *outputPath) {
  1058 + __strong typeof(weakSelf) strongSelf = weakSelf;
  1059 +
  1060 + /// 不限制大小
  1061 + [strongSelf qnUploadVideoWithToken:token file:outputPath progress:progress success:success failure:failure];
  1062 +
  1063 + } failure:^(NSString *errorMessage, NSError *error) {
  1064 +
  1065 + NSError *returnError = [NSError errorWithDomain:@"压缩失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"压缩失败,请重新获取"}];
  1066 + !failure ? : failure(nil,returnError);
  1067 + return;
  1068 +
  1069 + }];
  1070 +
  1071 +}
  1072 +
  1073 +
  1074 +///单个视频上传 - 压缩(七牛转码) - 限制 - 筛选) 实现
  1075 +- (void)uploadRequestPLShortVideoLimitWithToken:(NSString*)token asset:(id)asset outputPath:(NSString *)outputPath limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  1076 +
  1077 + //七牛token
  1078 + if ([NSString isEmpty:token]) {
  1079 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  1080 + !failure ? : failure(nil,error);
  1081 + return;
  1082 + }
  1083 +
  1084 + //上传路径
  1085 + if (!asset) {
  1086 + NSError *error = [NSError errorWithDomain:@"上传路径为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"上传为空,请重新获取"}];
  1087 + !failure ? : failure(nil,error);
  1088 + return;
  1089 + }
  1090 +
  1091 +
  1092 + __weak typeof(self) weakSelf = self;
  1093 +
  1094 + [CNLiveUploadManager zipVideoWithAsset:asset outputPath:outputPath limitType:limitType success:^(NSURL *url) {
  1095 + __strong typeof(weakSelf) strongSelf = weakSelf;
  1096 + AVAsset *avAsset = [AVAsset assetWithURL:url];
  1097 + NSLog(@"转码后时长%f",[[NSNumber numberWithFloat:CMTimeGetSeconds(avAsset.duration)] floatValue]);
  1098 + NSLog(@"转码后数据大小%ldmb",[NSData dataWithContentsOfURL:url].length / (1024*1024));
  1099 + //不限制大小
  1100 + [strongSelf qnUploadVideoWithToken:token file:url.path progress:progress success:success failure:failure];
  1101 +
  1102 + } progressCount:^(float progress) {
  1103 +
  1104 + // 更新压缩进度的 UI
  1105 + NSLog(@"transCoding progress: %f", progress);
  1106 +
  1107 + } failure:^{
  1108 +
  1109 + dispatch_async(dispatch_get_main_queue(), ^{
  1110 + NSError *returnError = [NSError errorWithDomain:@"压缩失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"压缩失败,请重新获取"}];
  1111 + !failure ? : failure(nil,returnError);
  1112 + return;
  1113 +
  1114 + });
  1115 +
  1116 + }];
  1117 +
  1118 +}
  1119 +
  1120 +
  1121 +
  1122 +#pragma mark - AFNetWorking
  1123 +/// (单张image - Image - 压缩或原图 - 限制 - 筛选) 实现
  1124 +- (void)afUploadLimitWithDic:(NSDictionary *)dic url:(NSString *)url image:(UIImage *)image isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  1125 +
  1126 + if (!image) {
  1127 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  1128 + !failure ? : failure(nil,error);
  1129 + return;
  1130 + }
  1131 +
  1132 + AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
  1133 + manager.requestSerializer.timeoutInterval = 15;//设置超时
  1134 + manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain", @"multipart/form-data", @"application/json", @"text/html",@"image/gif", @"image/jpeg", @"image/png", @"application/octet-stream", @"text/json", nil];
  1135 +
  1136 + [manager POST:url parameters:dic constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
  1137 +
  1138 + /*
  1139 + *该方法的参数
  1140 + 1. appendPartWithFileData:要上传的照片[二进制流]
  1141 + 2. name:对应网站上[upload.php中]处理文件的字段(比如upload)
  1142 + 3. fileName:要保存在服务器上的文件名
  1143 + 4. mimeType:上传的文件的类型
  1144 + */
  1145 + NSData *imageData = nil;
  1146 + NSString *fileName = [NSString stringWithFormat:@"Image%d",1];
  1147 + NSString *name = [NSString stringWithFormat:@"Image%d",1];
  1148 + NSString *mineType = @"image/jpeg";
  1149 + if (isOriginal) {
  1150 +
  1151 + if (UIImageJPEGRepresentation(image, 1.0)) {
  1152 + imageData = UIImageJPEGRepresentation(image, 1.0);
  1153 + }else {
  1154 + imageData = UIImagePNGRepresentation(image);
  1155 + }
  1156 +
  1157 + }else{
  1158 + imageData = [UIImage zipNSDataAndScaleWithImage:image];//非原图压缩;
  1159 + }
  1160 +
  1161 + if (!imageData) {
  1162 + NSError *returnError = [NSError errorWithDomain:@"压缩失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"压缩失败,请重新获取"}];
  1163 + !failure ? : failure(nil,returnError);
  1164 + return;
  1165 + }
  1166 + // 筛选
  1167 + if ( [CNLiveUploadManager isImageLimitType:limitType data:imageData]) {
  1168 +
  1169 + }else{
  1170 + NSError *error = [NSError errorWithDomain:@"数据过大" code:104 userInfo:@{NSLocalizedDescriptionKey:@"数据过大,请重新获取"}];
  1171 + !failure ? : failure(nil,error);
  1172 + return;
  1173 +
  1174 + }
  1175 +
  1176 + [formData appendPartWithFileData:imageData name:name fileName:fileName mimeType:mineType];
  1177 +
  1178 + } progress:^(NSProgress * _Nonnull uploadProgress) {
  1179 +
  1180 + !progress ? : progress(uploadProgress.fractionCompleted);
  1181 +
  1182 + } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
  1183 +
  1184 + if ([[responseObject objectForKey:@"errorCode"] isEqualToString:@"0"]) {
  1185 + //成功
  1186 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  1187 + uploadModel.responseObject = responseObject;
  1188 + uploadModel.code = @"200";
  1189 + uploadModel.index = 1;
  1190 + uploadModel.imageUrl = @"";
  1191 + uploadModel.message = @"上传成功";
  1192 +
  1193 + !success ? : success(uploadModel);
  1194 +
  1195 + }else
  1196 + {
  1197 + //失败
  1198 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  1199 + uploadModel.responseObject = responseObject;
  1200 + uploadModel.code = @"400";
  1201 + uploadModel.index = 1;
  1202 + uploadModel.imageUrl = @"";
  1203 + uploadModel.message = @"上传失败";
  1204 +
  1205 + !success ? : success(uploadModel);
  1206 +
  1207 + }
  1208 + } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
  1209 +
  1210 + !failure ? : failure(nil,error);
  1211 +
  1212 + }];
  1213 +
  1214 +
  1215 +}
  1216 +
  1217 +/// (单张Asset - Image - 压缩或原图 - 限制 - 筛选) 实现
  1218 +- (void)afUploadLimitWithDic:(NSDictionary *)dic url:(NSString *)url asset:(id)asset isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  1219 +
  1220 + if (!asset) {
  1221 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  1222 + !failure ? : failure(nil,error);
  1223 + return;
  1224 + }
  1225 +
  1226 + AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
  1227 + manager.requestSerializer.timeoutInterval = 15;//设置超时
  1228 + manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain", @"multipart/form-data", @"application/json", @"text/html",@"image/gif", @"image/jpeg", @"image/png", @"application/octet-stream", @"text/json", nil];
  1229 +
  1230 + [manager POST:url parameters:dic constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
  1231 +
  1232 + /*
  1233 + *该方法的参数
  1234 + 1. appendPartWithFileData:要上传的照片[二进制流]
  1235 + 2. name:对应网站上[upload.php中]处理文件的字段(比如upload)
  1236 + 3. fileName:要保存在服务器上的文件名
  1237 + 4. mimeType:上传的文件的类型
  1238 + */
  1239 + __block NSData *imageData = nil;
  1240 + NSString *fileName = [NSString stringWithFormat:@"Image%d",1];
  1241 + NSString *name = [NSString stringWithFormat:@"Image%d",1];
  1242 + NSString *mineType = @"image/jpeg";
  1243 + if ([PHAsset getAssetType:asset] == CNAssetModelMediaTypePhotoGif) {
  1244 + mineType = @"image/gif";
  1245 + }
  1246 +
  1247 + //压缩asset
  1248 + [PHAsset outputImageAsset:asset isOriginal:isOriginal success:^(NSData *data) {
  1249 + imageData = data;
  1250 + if (!imageData) {
  1251 + NSError *returnError = [NSError errorWithDomain:@"压缩失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"压缩失败,请重新获取"}];
  1252 + !failure ? : failure(nil,returnError);
  1253 + return;
  1254 + }
  1255 +
  1256 + // 筛选
  1257 + if ( [CNLiveUploadManager isImageLimitType:limitType data:imageData]) {
  1258 +
  1259 + }else{
  1260 + NSError *error = [NSError errorWithDomain:@"数据过大" code:104 userInfo:@{NSLocalizedDescriptionKey:@"数据过大,请重新获取"}];
  1261 + !failure ? : failure(nil,error);
  1262 + return;
  1263 +
  1264 + }
  1265 +
  1266 + [formData appendPartWithFileData:imageData name:name fileName:fileName mimeType:mineType];
  1267 +
  1268 + } failure:^{
  1269 +
  1270 + NSError *returnError = [NSError errorWithDomain:@"压缩失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"压缩失败,请重新获取"}];
  1271 + !failure ? : failure(nil,returnError);
  1272 +
  1273 + }];
  1274 +
  1275 +
  1276 + } progress:^(NSProgress * _Nonnull uploadProgress) {
  1277 +
  1278 + !progress ? : progress(uploadProgress.fractionCompleted);
  1279 +
  1280 + } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
  1281 +
  1282 + if ([[responseObject objectForKey:@"errorCode"] isEqualToString:@"0"]) {
  1283 + //成功
  1284 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  1285 + uploadModel.responseObject = responseObject;
  1286 + uploadModel.code = @"200";
  1287 + uploadModel.index = 1;
  1288 + uploadModel.imageUrl = @"";
  1289 + uploadModel.message = @"上传成功";
  1290 +
  1291 + !success ? : success(uploadModel);
  1292 +
  1293 + }else
  1294 + {
  1295 + //失败
  1296 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  1297 + uploadModel.responseObject = responseObject;
  1298 + uploadModel.code = @"400";
  1299 + uploadModel.index = 1;
  1300 + uploadModel.imageUrl = @"";
  1301 + uploadModel.message = @"上传失败";
  1302 +
  1303 + !success ? : success(uploadModel);
  1304 +
  1305 + }
  1306 + } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
  1307 +
  1308 + !failure ? : failure(nil,error);
  1309 +
  1310 + }];
  1311 +
  1312 +}
  1313 +
  1314 +/// (多张Image - ImageArray - 压缩或原图 - 限制 - 筛选) 实现
  1315 +- (void)afUploadLimitWithDic:(NSDictionary *)dic url:(NSString *)url imageArray:(NSMutableArray<UIImage *> *)imageArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  1316 +
  1317 + if (imageArray.count <= 0 ) {
  1318 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  1319 + !failure ? : failure(nil,error);
  1320 + return;
  1321 + }
  1322 +
  1323 + NSMutableArray *fileArray = [NSMutableArray array];
  1324 +
  1325 + AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
  1326 + manager.requestSerializer.timeoutInterval = 15;//设置超时
  1327 + manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain", @"multipart/form-data", @"application/json", @"text/html",@"image/gif", @"image/jpeg", @"image/png", @"application/octet-stream", @"text/json", nil];
  1328 +
  1329 + [manager POST:url parameters:dic constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
  1330 +
  1331 + //配置参数
  1332 + [imageArray enumerateObjectsUsingBlock:^(UIImage * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  1333 +
  1334 + /*
  1335 + *该方法的参数
  1336 + 1. appendPartWithFileData:要上传的照片[二进制流]
  1337 + 2. name:对应网站上[upload.php中]处理文件的字段(比如upload)
  1338 + 3. fileName:要保存在服务器上的文件名
  1339 + 4. mimeType:上传的文件的类型
  1340 + */
  1341 + UIImage *image = imageArray[idx];
  1342 + if (!image) {
  1343 + return;
  1344 + }
  1345 + NSData *imageData = nil;
  1346 + NSString *fileName = [NSString stringWithFormat:@"Image%ld",idx +1];
  1347 + NSString *name = [NSString stringWithFormat:@"Image%ld",idx +1];
  1348 + NSString *mineType = @"image/jpeg";
  1349 + if (isOriginal) {
  1350 +
  1351 + if (UIImageJPEGRepresentation(image, 1.0)) {
  1352 + imageData = UIImageJPEGRepresentation(image, 1.0);
  1353 + }else {
  1354 + imageData = UIImagePNGRepresentation(image);
  1355 + }
  1356 +
  1357 + }else{
  1358 + imageData = [UIImage zipNSDataAndScaleWithImage:image];//非原图压缩;
  1359 + }
  1360 +
  1361 + if (!imageData) {
  1362 + return;
  1363 + }
  1364 + // 筛选
  1365 + if ( [CNLiveUploadManager isImageLimitType:limitType data:imageData]) {
  1366 +
  1367 + }else{
  1368 + return;
  1369 +
  1370 + }
  1371 +
  1372 + [formData appendPartWithFileData:imageData name:name fileName:fileName mimeType:mineType];
  1373 +
  1374 + }];
  1375 +
  1376 +
  1377 + } progress:^(NSProgress * _Nonnull uploadProgress) {
  1378 +
  1379 + !progress ? : progress(uploadProgress.fractionCompleted);
  1380 +
  1381 + } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
  1382 +
  1383 + if ([[responseObject objectForKey:@"errorCode"] isEqualToString:@"0"]) {
  1384 + //成功
  1385 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  1386 + uploadModel.responseObject = responseObject;
  1387 + uploadModel.code = @"200";
  1388 + uploadModel.index = 1;
  1389 + uploadModel.imageUrl = @"";
  1390 + uploadModel.message = @"上传成功";
  1391 + [fileArray addObject:uploadModel];
  1392 + !success ? : success(fileArray);
  1393 +
  1394 + }else
  1395 + {
  1396 + //失败
  1397 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  1398 + uploadModel.responseObject = responseObject;
  1399 + uploadModel.code = @"400";
  1400 + uploadModel.index = 1;
  1401 + uploadModel.imageUrl = @"";
  1402 + uploadModel.message = @"上传失败";
  1403 + [fileArray addObject:uploadModel];
  1404 + !success ? : success(fileArray);
  1405 +
  1406 + }
  1407 + } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
  1408 +
  1409 + !failure ? : failure(nil,error);
  1410 +
  1411 + }];
  1412 +
  1413 +
  1414 +}
  1415 +
  1416 +/// (多张Asset - AssetArray - 压缩或原图 - 限制 - 筛选) 实现
  1417 +- (void)afUploadLimitWithDic:(NSDictionary *)dic url:(NSString *)url assetArray:(NSMutableArray *)assetArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  1418 +
  1419 + if (assetArray.count <= 0 ) {
  1420 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  1421 + !failure ? : failure(nil,error);
  1422 + return;
  1423 + }
  1424 + NSMutableArray *fileArray = [NSMutableArray array];
  1425 +
  1426 + AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
  1427 + manager.requestSerializer.timeoutInterval = 15;//设置超时
  1428 + manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain", @"multipart/form-data", @"application/json", @"text/html",@"image/gif", @"image/jpeg", @"image/png", @"application/octet-stream", @"text/json", nil];
  1429 +
  1430 + [manager POST:url parameters:dic constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
  1431 +
  1432 +
  1433 + [assetArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  1434 +
  1435 + /*
  1436 + *该方法的参数
  1437 + 1. appendPartWithFileData:要上传的照片[二进制流]
  1438 + 2. name:对应网站上[upload.php中]处理文件的字段(比如upload)
  1439 + 3. fileName:要保存在服务器上的文件名
  1440 + 4. mimeType:上传的文件的类型
  1441 + */
  1442 + id asset = assetArray[idx];
  1443 + if (!asset) {
  1444 + return;
  1445 + }
  1446 + __block NSData *imageData = nil;
  1447 + NSString *fileName = [NSString stringWithFormat:@"Image%ld",idx+1];
  1448 + NSString *name = [NSString stringWithFormat:@"Image%ld",idx+1];
  1449 + NSString *mineType = @"image/jpeg";
  1450 + if ([PHAsset getAssetType:asset] == CNAssetModelMediaTypePhotoGif) {
  1451 + mineType = @"image/gif";
  1452 + }
  1453 +
  1454 +
  1455 + //压缩asset
  1456 + [PHAsset outputImageAsset:asset isOriginal:isOriginal success:^(NSData *data) {
  1457 + imageData = data;
  1458 + if (!imageData) {
  1459 + NSError *returnError = [NSError errorWithDomain:@"压缩失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"压缩失败,请重新获取"}];
  1460 + !failure ? : failure(nil,returnError);
  1461 + return;
  1462 + }
  1463 +
  1464 + // 筛选
  1465 + if ( [CNLiveUploadManager isImageLimitType:limitType data:imageData]) {
  1466 +
  1467 + }else{
  1468 + NSError *error = [NSError errorWithDomain:@"数据过大" code:104 userInfo:@{NSLocalizedDescriptionKey:@"数据过大,请重新获取"}];
  1469 + !failure ? : failure(nil,error);
  1470 + return;
  1471 +
  1472 + }
  1473 +
  1474 + [formData appendPartWithFileData:imageData name:name fileName:fileName mimeType:mineType];
  1475 +
  1476 + } failure:^{
  1477 + NSError *returnError = [NSError errorWithDomain:@"压缩失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"压缩失败,请重新获取"}];
  1478 + !failure ? : failure(nil,returnError);
  1479 + return;
  1480 +
  1481 + }];
  1482 +
  1483 + }];
  1484 +
  1485 + } progress:^(NSProgress * _Nonnull uploadProgress) {
  1486 +
  1487 + !progress ? : progress(uploadProgress.fractionCompleted);
  1488 +
  1489 + } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
  1490 +
  1491 + if ([[responseObject objectForKey:@"errorCode"] isEqualToString:@"0"]) {
  1492 + //成功
  1493 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  1494 + uploadModel.responseObject = responseObject;
  1495 + uploadModel.code = @"200";
  1496 + uploadModel.index = 1;
  1497 + uploadModel.imageUrl = @"";
  1498 + uploadModel.message = @"上传成功";
  1499 +
  1500 + [fileArray addObject:uploadModel];
  1501 + !success ? : success(fileArray);
  1502 +
  1503 + }else
  1504 + {
  1505 + //失败
  1506 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  1507 + uploadModel.responseObject = responseObject;
  1508 + uploadModel.code = @"400";
  1509 + uploadModel.index = 1;
  1510 + uploadModel.imageUrl = @"";
  1511 + uploadModel.message = @"上传失败";
  1512 +
  1513 + [fileArray addObject:uploadModel];
  1514 + !success ? : success(fileArray);
  1515 +
  1516 + }
  1517 + } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
  1518 +
  1519 + !failure ? : failure(nil,error);
  1520 +
  1521 + }];
  1522 +
  1523 +}
  1524 +
  1525 +
  1526 +#pragma mark - 业务部分
  1527 +
  1528 +/// 单图上传 (asset取得Image - 压缩或原图 - 限制 - 筛选)
  1529 ++ (void)uploadLimitType:(CNLiveUploadType)type asset:(id)asset isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType token:(NSString *)token progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  1530 +
  1531 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1532 +
  1533 + if ([asset isKindOfClass:[PHAsset class]]) {
  1534 +
  1535 + [[CNLiveUploadManager shareInsance]qnUploadLimitWithToken:token phAsset:(PHAsset *)asset isOriginal:(BOOL) isOriginal limitType:limitType progress:progress success:success failure:failure];
  1536 +
  1537 + }
  1538 +
  1539 + }else if (type == CNLiveUploadTypeKS) {
  1540 +
  1541 + }else{
  1542 +
  1543 + }
  1544 +}
  1545 +
  1546 +
  1547 +/// 单图上传 (Image - 压缩或原图 - 限制 - 筛选)
  1548 ++ (void)uploadLimitType:(CNLiveUploadType)type image:(UIImage *)image isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType token:(NSString *)token progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  1549 +
  1550 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1551 +
  1552 + [[CNLiveUploadManager shareInsance]qnUploadLimitWithToken:token image:image isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1553 +
  1554 + }else if (type == CNLiveUploadTypeKS) {
  1555 +
  1556 + }else{
  1557 +
  1558 + }
  1559 +
  1560 +}
  1561 +
  1562 +/// 多张图上传 (images - 压缩或原图 - 限制 - 筛选)
  1563 ++ (void)uploadLimitType:(CNLiveUploadType)type imageArray:(NSMutableArray *)imageArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType token:(NSString *)token progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  1564 +
  1565 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1566 + [[CNLiveUploadManager shareInsance] qnUploadLimitWithToken:token imageArray:imageArray isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1567 +
  1568 + }else if (type == CNLiveUploadTypeKS) {
  1569 +
  1570 + }else{
  1571 +
  1572 + }
  1573 +
  1574 +}
  1575 +
  1576 +/// 多张图上传 (assetArray - 压缩 - 限制 - 筛选)
  1577 ++ (void)uploadLimitType:(CNLiveUploadType)type token:(NSString *)token assetArray:(NSMutableArray *)assetArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  1578 +
  1579 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1580 + [[CNLiveUploadManager shareInsance] qnUploadLimitWithToken:token assetArray:assetArray isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1581 +
  1582 + }else if (type == CNLiveUploadTypeKS) {
  1583 +
  1584 + }else{
  1585 +
  1586 + }
  1587 +
  1588 +}
  1589 +
  1590 +
  1591 +/// 单个视频上传 (video - 压缩 - 限制 - 筛选)
  1592 ++ (void)uploadLimitVideoType:(CNLiveUploadType)type token:(NSString *)token asset:(id)asset outputPath:(NSString *)outputPath progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  1593 +
  1594 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1595 + [[CNLiveUploadManager shareInsance] qnUploadVideoLimitWithToken:token asset:asset outputPath:outputPath progress:progress success:success failure:failure];
  1596 +
  1597 + }else if (type == CNLiveUploadTypeKS) {
  1598 +
  1599 + }else{
  1600 +
  1601 + }
  1602 +
  1603 +}
  1604 +
  1605 +#pragma mark - 请求token 上传
  1606 +/// 请求token 单张上传 (asset - 压缩 - 限制 - 筛选)
  1607 ++ (void)uploadRequestType:(CNLiveUploadType)type url:(NSString *)url dic:(NSDictionary *)dic asset:(id)asset isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure{
  1608 +
  1609 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1610 + [[HttpService service] sendRequestWithHttpMethod:E_HTTP_REQUEST_METHOD_POST URLPath:url parameters:dic isCache:NO CheckParam:nil completionHandler:^(id data, NSError *error) {
  1611 +
  1612 + NSDictionary *dic = (NSDictionary *)data;
  1613 + if (!error && [dic containsObjectForKey:@"token"]) {
  1614 + NSString *token = dic[@"token"];
  1615 + if ([asset isKindOfClass:[PHAsset class]]) {
  1616 +
  1617 + [[CNLiveUploadManager shareInsance]qnUploadLimitWithToken:token phAsset:(PHAsset *)asset isOriginal:(BOOL) isOriginal limitType:limitType progress:progress success:success failure:failure];
  1618 +
  1619 + }else {
  1620 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  1621 + !failure ? : failure(nil,error);
  1622 + return;
  1623 + }
  1624 +
  1625 + } else {//请求token失败
  1626 +
  1627 + NSError *error = [NSError errorWithDomain:@"请求token失败" code:100 userInfo:@{NSLocalizedDescriptionKey:@"请求token失败,请重新获取"}];
  1628 + !failure ? : failure(nil,error);
  1629 + return;
  1630 + }
  1631 +
  1632 + }];
  1633 +
  1634 +
  1635 + }else if (type == CNLiveUploadTypeKS) {
  1636 +
  1637 + }else{
  1638 + [[CNLiveUploadManager shareInsance]afUploadLimitWithDic:dic url:url asset:asset isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1639 +
  1640 + }
  1641 +
  1642 +}
  1643 +
  1644 +/// 请求token 单图上传 (Image - 压缩或原图 - 限制 - 筛选)
  1645 ++ (void)uploadRequestType:(CNLiveUploadType)type url:(NSString *)url dic:(NSDictionary *)dic image:(UIImage *)image isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  1646 +
  1647 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1648 + [[HttpService service] sendRequestWithHttpMethod:E_HTTP_REQUEST_METHOD_POST URLPath:url parameters:dic isCache:NO CheckParam:nil completionHandler:^(id data, NSError *error) {
  1649 +
  1650 + NSDictionary *dic = (NSDictionary *)data;
  1651 + if (!error && [dic containsObjectForKey:@"token"]) {
  1652 + NSString *token = dic[@"token"];
  1653 + [[CNLiveUploadManager shareInsance]qnUploadLimitWithToken:token image:image isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1654 +
  1655 + } else {//请求token失败
  1656 +
  1657 + NSError *error = [NSError errorWithDomain:@"请求token失败" code:100 userInfo:@{NSLocalizedDescriptionKey:@"请求token失败,请重新获取"}];
  1658 + !failure ? : failure(nil,error);
  1659 + return;
  1660 + }
  1661 +
  1662 + }];
  1663 +
  1664 +
  1665 + }else if (type == CNLiveUploadTypeKS) {
  1666 +
  1667 + }else{
  1668 + [[CNLiveUploadManager shareInsance]afUploadLimitWithDic:dic url:url image:image isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1669 +
  1670 + }
  1671 +
  1672 +}
  1673 +
  1674 +/// 请求token 多张图上传 (images - 压缩或原图 - 限制 - 筛选)
  1675 ++ (void)uploadRequestType:(CNLiveUploadType)type url:(NSString *)url dic:(NSDictionary *)dic imageArray:(NSMutableArray *)imageArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  1676 +
  1677 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1678 + [[HttpService service] sendRequestWithHttpMethod:E_HTTP_REQUEST_METHOD_POST URLPath:url parameters:dic isCache:NO CheckParam:nil completionHandler:^(id data, NSError *error) {
  1679 +
  1680 + NSDictionary *dic = (NSDictionary *)data;
  1681 + if (!error && [dic containsObjectForKey:@"token"]) {
  1682 + NSString *token = dic[@"token"];
  1683 + [[CNLiveUploadManager shareInsance] qnUploadLimitWithToken:token imageArray:imageArray isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1684 +
  1685 + } else {//请求token失败
  1686 +
  1687 + NSError *error = [NSError errorWithDomain:@"请求token失败" code:100 userInfo:@{NSLocalizedDescriptionKey:@"请求token失败,请重新获取"}];
  1688 + !failure ? : failure(nil,error);
  1689 + return;
  1690 + }
  1691 +
  1692 + }];
  1693 +
  1694 +
  1695 + }else if (type == CNLiveUploadTypeKS) {
  1696 +
  1697 + }else{
  1698 + [[CNLiveUploadManager shareInsance]afUploadLimitWithDic:dic url:url imageArray:imageArray isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1699 +
  1700 + }
  1701 +
  1702 +}
  1703 +
  1704 +/// 请求token (assetArray - 压缩 - 限制 - 筛选)
  1705 ++ (void)uploadRequestType:(CNLiveUploadType)type url:(NSString *)url dic:(NSDictionary *)dic assetArray:(NSMutableArray *)assetArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  1706 +
  1707 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1708 + [[HttpService service] sendRequestWithHttpMethod:E_HTTP_REQUEST_METHOD_POST URLPath:url parameters:dic isCache:NO CheckParam:nil completionHandler:^(id data, NSError *error) {
  1709 +
  1710 + NSDictionary *dic = (NSDictionary *)data;
  1711 + if (!error && [dic containsObjectForKey:@"token"]) {
  1712 + NSString *token = dic[@"token"];
  1713 + [[CNLiveUploadManager shareInsance] qnUploadLimitWithToken:token assetArray:assetArray isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1714 +
  1715 + } else {//请求token失败
  1716 +
  1717 + NSError *error = [NSError errorWithDomain:@"请求token失败" code:100 userInfo:@{NSLocalizedDescriptionKey:@"请求token失败,请重新获取"}];
  1718 + !failure ? : failure(nil,error);
  1719 + return;
  1720 + }
  1721 +
  1722 + }];
  1723 +
  1724 +
  1725 + }else if (type == CNLiveUploadTypeKS) {
  1726 +
  1727 + }else{
  1728 + [[CNLiveUploadManager shareInsance] afUploadLimitWithDic:dic url:url assetArray:assetArray isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1729 +
  1730 + }
  1731 +
  1732 +}
  1733 +
  1734 +/// 请求token 单个视频上传 (video - 压缩 - 限制 - 筛选)
  1735 ++ (void)uploadRequestVideoType:(CNLiveUploadType)type url:(NSString *)url dic:(NSDictionary *)dic asset:(id)asset outputPath:(NSString *)outputPath progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  1736 +
  1737 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1738 + [[HttpService service] sendRequestWithHttpMethod:E_HTTP_REQUEST_METHOD_POST URLPath:url parameters:dic isCache:NO CheckParam:nil completionHandler:^(id data, NSError *error) {
  1739 +
  1740 + NSDictionary *dic = (NSDictionary *)data;
  1741 + if (!error && [dic containsObjectForKey:@"token"]) {
  1742 + NSString *token = dic[@"token"];
  1743 + [[CNLiveUploadManager shareInsance] qnUploadVideoLimitWithToken:token asset:asset outputPath:outputPath progress:progress success:success failure:failure];
  1744 +
  1745 + } else {//请求token失败
  1746 +
  1747 + NSError *error = [NSError errorWithDomain:@"请求token失败" code:100 userInfo:@{NSLocalizedDescriptionKey:@"请求token失败,请重新获取"}];
  1748 + !failure ? : failure(nil,error);
  1749 + return;
  1750 + }
  1751 +
  1752 + }];
  1753 +
  1754 +
  1755 + }else if (type == CNLiveUploadTypeKS) {
  1756 +
  1757 + }else{
  1758 +
  1759 + }
  1760 +
  1761 +}
  1762 +
  1763 +/// 请求token 单个视频上传 (video - 七牛短视频压缩 - 限制 - 筛选)
  1764 ++ (void)uploadRequestWhithPLShortVideoType:(CNLiveUploadType)type outputPath:(NSString *)outputPath url:(NSString *)url dic:(NSDictionary *)dic asset:(id)asset limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  1765 +
  1766 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1767 + [[HttpService service] sendRequestWithHttpMethod:E_HTTP_REQUEST_METHOD_POST URLPath:url parameters:dic isCache:NO CheckParam:nil completionHandler:^(id data, NSError *error) {
  1768 +
  1769 + NSDictionary *dic = (NSDictionary *)data;
  1770 + if (!error && [dic containsObjectForKey:@"token"]) {
  1771 + NSString *token = dic[@"token"];
  1772 + [[CNLiveUploadManager shareInsance] uploadRequestPLShortVideoLimitWithToken:token asset:asset outputPath:outputPath limitType:limitType progress:progress success:success failure:failure];
  1773 +
  1774 + } else {//请求token失败
  1775 + NSError *error = [NSError errorWithDomain:@"请求token失败" code:100 userInfo:@{NSLocalizedDescriptionKey:@"请求token失败,请重新获取"}];
  1776 + !failure ? : failure(nil,error);
  1777 + return;
  1778 + }
  1779 +
  1780 + }];
  1781 +
  1782 + }else if (type == CNLiveUploadTypeKS) {
  1783 +
  1784 + }else{
  1785 +
  1786 + }
  1787 +
  1788 +}
  1789 +
  1790 +
  1791 +#pragma mark - 私有方法
  1792 +///筛选 是否视频在限制内
  1793 ++ (BOOL)isVideoLimitType:(AppPhototLimitType)limitType data:(NSData *)data{
  1794 + switch (limitType) {
  1795 + case AppPhototLimitTypeChat://聊天视频
  1796 + if (data.length <= kChat_limit_video) {
  1797 + return YES;
  1798 + }else{
  1799 + return NO;
  1800 + }
  1801 + break;
  1802 + case AppPhototLimitTypeFriendsCircle://朋友圈
  1803 + if (data.length <= kFirendsCircle_limit_video) {
  1804 + return YES;
  1805 + }else{
  1806 + return NO;
  1807 + }
  1808 + break;
  1809 +
  1810 + default:
  1811 + if (data.length <= 20*1024*1024) {
  1812 + return YES;
  1813 + }else{
  1814 + return NO;
  1815 + }
  1816 + break;
  1817 + }
  1818 +}
  1819 +
  1820 +/// 筛选 是否图片在限制内
  1821 ++ (BOOL)isImageLimitType:(AppPhototLimitType)limitType data:(NSData *)data {
  1822 +
  1823 +
  1824 + switch (limitType) {
  1825 + case AppPhototLimitTypeChat://聊天
  1826 + if (data.length <= kChat_limit_photo) {
  1827 + return YES;
  1828 + }else{
  1829 + return NO;
  1830 + }
  1831 + break;
  1832 + case AppPhototLimitTypeFriendsCircle://朋友圈
  1833 + if (data.length <= kFriendsCircle_limit_photo) {
  1834 + return YES;
  1835 + }else{
  1836 + return NO;
  1837 + }
  1838 + break;
  1839 + case AppPhototLimitTypeSweepCode://扫码
  1840 + if (data.length <= kSweepCode_limit_phoho) {
  1841 + return YES;
  1842 + }else{
  1843 + return NO;
  1844 + }
  1845 + break;
  1846 + case AppPhototLimitTypeTarentoComment://评论
  1847 + if (data.length <= kTarentoComment_limit_photo) {
  1848 + return YES;
  1849 + }else{
  1850 + return NO;
  1851 + }
  1852 + break;
  1853 +
  1854 + default:
  1855 + if (data.length <= 10*1024*1024) {
  1856 + return YES;
  1857 + }else{
  1858 + return NO;
  1859 + }
  1860 + break;
  1861 + }
  1862 +
  1863 +}
  1864 +
  1865 +
  1866 +#pragma mark - 七牛短视频设置方法
  1867 +
  1868 +/// 短视频分辨率转码导出
  1869 ++ (void)zipVideoWithAsset:(id) asset outputPath:(NSString *)outputPath limitType:(AppPhototLimitType)limitType success:(void(^)(NSURL * url))success progressCount:(void(^)(float progress)) progressCount failure:(void(^)(void))failure {
  1870 +
  1871 + //取得url
  1872 + NSURL *url = [PHAsset movieURLWithAsset:asset];
  1873 + NSInteger dataLInt = [NSData dataWithContentsOfURL:url].length;
  1874 + NSNumber *dataNumber = [NSNumber numberWithInteger:dataLInt];
  1875 + float dataL = [dataNumber floatValue];
  1876 + NSLog(@"转码前数据大小%f",dataL / (1024.0*1024.0));
  1877 + //编辑原始数据
  1878 + NSMutableDictionary *movieSettings = [[NSMutableDictionary alloc]init];
  1879 + AVAsset *avAsset = [AVAsset assetWithURL:url];
  1880 + movieSettings[PLSURLKey] = url;
  1881 + movieSettings[PLSAssetKey] = avAsset;
  1882 + movieSettings[PLSStartTimeKey] = [NSNumber numberWithFloat:0.f];//开始时间
  1883 + movieSettings[PLSDurationKey] = [NSNumber numberWithFloat:CMTimeGetSeconds(avAsset.duration)];//时长
  1884 + //设置进行压缩
  1885 + CGFloat start = [movieSettings[PLSStartTimeKey] floatValue];
  1886 + CGFloat duration = [movieSettings[PLSDurationKey] floatValue];
  1887 + NSLog(@"转码前输出时长:%f.2",duration);
  1888 + CMTimeRange timeRange = CMTimeRangeMake(CMTimeMake(start * 1000, 1000), CMTimeMake(duration * 1000, 1000));
  1889 + PLShortVideoTranscoder *shortVideoTranscoder = [[PLShortVideoTranscoder alloc] initWithURL:url];
  1890 +
  1891 + NSString *path = [NSString string];
  1892 + if (outputPath.length <= 0 || outputPath) {
  1893 + NSDateFormatter *formater = [[NSDateFormatter alloc] init];
  1894 + [formater setDateFormat:@"yyyy-MM-dd-HH:mm:ss-SSS"];
  1895 + path = [NSHomeDirectory() stringByAppendingFormat:@"/tmp/output-%@.mp4", [formater stringFromDate:[NSDate date]]];
  1896 +
  1897 + }else {
  1898 + path = outputPath;
  1899 + }
  1900 +
  1901 + NSLog(@"输出转码前视频路径%@",path);
  1902 + shortVideoTranscoder.outputURL = [NSURL fileURLWithPath:path];
  1903 + shortVideoTranscoder.outputFileType = PLSFileTypeMPEG4;
  1904 + shortVideoTranscoder.outputFilePreset = [CNLiveUploadManager presetWithVideoLimitType:limitType url:url dataL:dataL];//分辨率
  1905 + shortVideoTranscoder.bitrate = [CNLiveUploadManager bitrateWithPreset:shortVideoTranscoder.outputFilePreset avAsset:avAsset url:url dataL:dataL];
  1906 + shortVideoTranscoder.timeRange = timeRange;
  1907 + shortVideoTranscoder.rotateOrientation = PLSPreviewOrientationPortrait; //视频显示
  1908 + shortVideoTranscoder.videoSelectedRect = CGRectZero; //视频剪裁区域
  1909 + shortVideoTranscoder.videoFrameRate = 0; //帧率
  1910 + //成功
  1911 + [shortVideoTranscoder setCompletionBlock:^(NSURL *url){
  1912 + NSLog(@"输出转码后视频路径%@",url.path);
  1913 + NSLog(@"输出转码后数据大小%ld",[NSData dataWithContentsOfURL:url].length / (1024*1024));
  1914 + dispatch_async(dispatch_get_main_queue(), ^{
  1915 + !success ? : success(url);
  1916 + });
  1917 +
  1918 + }];
  1919 +
  1920 + //失败
  1921 + [shortVideoTranscoder setFailureBlock:^(NSError *error){
  1922 + NSLog(@"输出错误%@",error);
  1923 + dispatch_async(dispatch_get_main_queue(), ^{
  1924 + !failure ? : failure();
  1925 + });
  1926 +
  1927 + }];
  1928 +
  1929 + [shortVideoTranscoder setProcessingBlock:^(float progress){
  1930 + // 更新压缩进度的 UI
  1931 +
  1932 + NSLog(@"transCoding progress: %f", progress);
  1933 + !progressCount ? : progressCount(progress);
  1934 + }];
  1935 +
  1936 + [shortVideoTranscoder startTranscoding];
  1937 +
  1938 +
  1939 +}
  1940 +
  1941 +/// 根据限制获取视频分辨率
  1942 ++ (PLSFilePreset)presetWithVideoLimitType:(AppPhototLimitType)limitType url:(NSURL *)url dataL:(float)dataL{
  1943 +
  1944 + NSLog(@"1输出转码前数据长度%f",(dataL/(1024.0*1024)));
  1945 + if (limitType == AppPhototLimitTypeChat) {//聊天
  1946 + if (dataL > kCNUploadSize30MB) {
  1947 + return PLSFilePreset640x480;
  1948 + }else {
  1949 + return PLSFilePreset960x540;
  1950 + }
  1951 +
  1952 + }else if (limitType == AppPhototLimitTypeFriendsCircle) {//朋友圈
  1953 + if (dataL > kCNUploadSize30MB) {
  1954 + return PLSFilePreset640x480;
  1955 + }else {
  1956 + return PLSFilePreset960x540;
  1957 + }
  1958 +
  1959 + }else if (limitType == AppPhototLimitTypeSweepCode) {//扫码
  1960 + if (dataL > kCNUploadSize30MB) {
  1961 + return PLSFilePreset640x480;
  1962 + }else {
  1963 + return PLSFilePreset960x540;
  1964 + }
  1965 + }else if (limitType == AppPhototLimitTypeTarentoComment) {//评论
  1966 + if (dataL > kCNUploadSize30MB) {
  1967 + return PLSFilePreset640x480;
  1968 + }else {
  1969 + return PLSFilePreset960x540;
  1970 + }
  1971 +
  1972 + }else {
  1973 + if (dataL > kCNUploadSize30MB) {//其他
  1974 + return PLSFilePreset640x480;
  1975 + }else {
  1976 + return PLSFilePreset960x540;
  1977 + }
  1978 + }
  1979 +
  1980 +}
  1981 +
  1982 +///根据分辨力设置码率
  1983 ++ (float)bitrateWithPreset:(PLSFilePreset)perset avAsset:(AVAsset *)avAsset url:(NSURL *)url dataL:(float)dataL{
  1984 +
  1985 + float bitrate = avAsset.pls_bitrate;
  1986 +
  1987 + if (perset == PLSFilePresetLowQuality) {
  1988 + return 700 * 1000;
  1989 + }else if (perset == PLSFilePresetMediumQuality) {
  1990 + return 3000 * 1000;
  1991 + }else if (perset == PLSFilePresetHighestQuality) {
  1992 + return 6000 * 1000;
  1993 + }else {
  1994 + if (dataL > 150*1024*1024) {
  1995 + float scale = (20*1024*1024)/dataL;
  1996 + if (bitrate *scale > 300 * 1000) {
  1997 + return 300 *1000;
  1998 + }else {
  1999 + return bitrate *scale;
  2000 + }
  2001 + }else if (dataL > 50*1024*1024) {
  2002 + float scale = (25*1024*1024)/dataL;
  2003 + if (bitrate *scale > 400 * 1000) {
  2004 + return 400 *1000;
  2005 + }else {
  2006 + return bitrate *scale;
  2007 + }
  2008 +
  2009 + }else if (dataL > 40*1024*1024) {
  2010 + if (bitrate *0.4 > 550 * 1000) {
  2011 + return 550 *1000;
  2012 + }else {
  2013 + return bitrate *0.40;
  2014 + }
  2015 +
  2016 + }else if (dataL > 30*1024*1024) {
  2017 +
  2018 + if (bitrate *0.60 > 700 * 1000) {
  2019 + return 700 *1000;
  2020 + }else {
  2021 + return bitrate *0.60;
  2022 + }
  2023 + }else if (dataL > 20*1024*1024) {
  2024 +
  2025 + return bitrate *0.80;
  2026 + }else if (dataL > 10*1024*1024) {
  2027 +
  2028 + return bitrate *0.9;
  2029 + }else {
  2030 + return bitrate;
  2031 + }
  2032 + }
  2033 +
  2034 +}
  2035 +
  2036 +
  2037 +#pragma mark - 金山
  2038 +
  2039 +#pragma mark - 导出
  2040 +
  2041 +
  2042 +
  2043 +@end
  2044 +
  2045 +
  2046 +
  2047 +#pragma mark - CNLiveUploadModel
  2048 +
  2049 +@implementation CNLiveUploadModel
  2050 +
  2051 +- (instancetype)init
  2052 +{
  2053 + self = [super init];
  2054 + if (self) {
  2055 +
  2056 + _code = @"";
  2057 + _index = 0;
  2058 + _imageUrl = @"";
  2059 + _file = @"";
  2060 + _message = @"";
  2061 + _image = nil;
  2062 + _imageW = 0;
  2063 + _imageH = 0;
  2064 + _asset = nil;
  2065 + _info = nil;
  2066 + _key = @"";
  2067 + _resp = nil;
  2068 + _responseObject = nil;
  2069 +
  2070 + }
  2071 + return self;
  2072 +}
  2073 +
  2074 +
  2075 +
  2076 +
  2077 +@end
  2078 +
  2079 +
... ...
CNLiveUploadManager/压缩图片/PHAsset+zipData.h 0 → 100644
  1 +//
  2 +// PHAsset+zipData.h
  3 +// CNLiveUploadManager_Demo
  4 +//
  5 +// Created by 梁星国 on 2018/10/30.
  6 +// Copyright © 2018年 梁星国. All rights reserved.
  7 +//
  8 +
  9 +#import <Photos/Photos.h>
  10 +#import <PLShortVideoKit/PLShortVideoKit.h>
  11 +@class CNLiveUploadModel;
  12 +
  13 +NS_ASSUME_NONNULL_BEGIN
  14 +
  15 +typedef enum : NSUInteger {
  16 + CNAssetModelMediaTypePhoto = 0, //图片
  17 + CNAssetModelMediaTypeLivePhoto, //动态壁纸
  18 + CNAssetModelMediaTypePhotoGif, //gif
  19 + CNAssetModelMediaTypeVideo, //视频
  20 + CNAssetModelMediaTypeAudio //音频
  21 +} CNAssetModelMediaType;
  22 +
  23 +@interface PHAsset (zipData)
  24 +
  25 +/// 取得asset类型
  26 ++ (CNAssetModelMediaType)getAssetType:(id)asset;
  27 +
  28 +/// 取得URL
  29 ++ (NSURL *)movieURLWithAsset:(id) asset;
  30 +
  31 +/// 图片压缩
  32 ++ (void )outputImageAsset:(id) asset isOriginal:(BOOL) isOriginal success:(void(^)(NSData * data))success failure:(void(^)(void))failure;
  33 +
  34 +/// 导出视频
  35 ++ (void)getVideoWithAsset:(PHAsset *)asset outputPath:(NSString *)OutputPath presetName:(NSString *)presetName success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure;
  36 +
  37 +@end
  38 +
  39 +NS_ASSUME_NONNULL_END
... ...
CNLiveUploadManager/压缩图片/PHAsset+zipData.m 0 → 100644
  1 +//
  2 +// PHAsset+zipData.m
  3 +// CNLiveUploadManager_Demo
  4 +//
  5 +// Created by 梁星国 on 2018/10/30.
  6 +// Copyright © 2018年 梁星国. All rights reserved.
  7 +//
  8 +
  9 +#import "PHAsset+zipData.h"
  10 +#import "UIImage+zipData.h"
  11 +
  12 +@implementation PHAsset (zipData)
  13 +
  14 +/// 取得asset类型
  15 ++ (CNAssetModelMediaType)getAssetType:(id)asset {
  16 +
  17 + CNAssetModelMediaType type = CNAssetModelMediaTypePhoto;
  18 + PHAsset *phAsset = (PHAsset *)asset;
  19 + if (phAsset.mediaType == PHAssetMediaTypeVideo) {
  20 + type = CNAssetModelMediaTypeVideo;
  21 + }else if (phAsset.mediaType == PHAssetMediaTypeAudio) {
  22 + type = CNAssetModelMediaTypeAudio;
  23 + }else if (phAsset.mediaType == PHAssetMediaTypeImage) {
  24 + if (@available(iOS 9.1, *)) {
  25 + // if (asset.mediaSubtypes == PHAssetMediaSubtypePhotoLive) type = TZAssetModelMediaTypeLivePhoto;
  26 + }
  27 + // Gif
  28 + if ([[phAsset valueForKey:@"filename"] hasSuffix:@"GIF"]) {
  29 + type = CNAssetModelMediaTypePhotoGif;
  30 + }
  31 + }
  32 + return type;
  33 +}
  34 +
  35 +/// 获取视频URL
  36 ++ (NSURL *)movieURLWithAsset:(id) asset {
  37 + __block NSURL *url = nil;
  38 +
  39 + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
  40 + if ([PHAsset getAssetType:asset] == CNAssetModelMediaTypeVideo) {
  41 + PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
  42 + options.version = PHVideoRequestOptionsVersionOriginal;
  43 + options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
  44 + options.networkAccessAllowed = YES;
  45 +
  46 + PHImageManager *manager = [PHImageManager defaultManager];
  47 + [manager requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
  48 + AVURLAsset *urlAsset = (AVURLAsset *)asset;
  49 + url = urlAsset.URL;
  50 +
  51 + dispatch_semaphore_signal(semaphore);
  52 + }];
  53 + }
  54 +
  55 + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
  56 +
  57 + return url;
  58 +}
  59 +
  60 +
  61 +/// 图片压缩
  62 ++ (void )outputImageAsset:(id) asset isOriginal:(BOOL) isOriginal success:(void(^)(NSData * data))success failure:(void(^)(void))failure {
  63 +
  64 + if ([asset isKindOfClass:[PHAsset class]]) {
  65 +
  66 + __block NSData *data = nil;
  67 + if ([PHAsset getAssetType:asset] == CNAssetModelMediaTypePhotoGif) {
  68 +
  69 + PHImageManager *imageManager = [PHImageManager defaultManager];
  70 + PHImageRequestOptions *options = [PHImageRequestOptions new];
  71 + options.deliveryMode = PHImageRequestOptionsDeliveryModeFastFormat;
  72 + options.resizeMode = PHImageRequestOptionsResizeModeFast;
  73 + options.synchronous = NO;
  74 + [imageManager requestImageDataForAsset:asset options:options resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
  75 + if (imageData) {
  76 + data = imageData;
  77 + !success ? : success(data);
  78 + }else {
  79 + !failure ? : failure();
  80 + }
  81 + }];
  82 +
  83 + }else {//图片
  84 +
  85 + PHImageManager *imageManager = [PHImageManager defaultManager];
  86 + PHImageRequestOptions *options = [PHImageRequestOptions new];
  87 + options.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;
  88 + options.resizeMode = PHImageRequestOptionsResizeModeFast;
  89 + options.synchronous = NO;
  90 + [imageManager requestImageDataForAsset:asset options:options resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
  91 + if (imageData) {
  92 + UIImage *result = [UIImage imageWithData:imageData];
  93 + if (result) {
  94 +
  95 + if (isOriginal) {//是原图
  96 + if (UIImageJPEGRepresentation(result, 1.0)) {
  97 + data = UIImageJPEGRepresentation(result, 1.0);
  98 + }else {
  99 + data = UIImagePNGRepresentation(result);
  100 + }
  101 + }else{//不是原图
  102 + data = [UIImage zipNSDataAndScaleWithImage:result];//压缩
  103 + }
  104 + !success ? : success(data);
  105 +
  106 + }else{
  107 + !failure ? : failure();
  108 + }
  109 +
  110 + }else {
  111 + !failure ? : failure();
  112 + }
  113 + }];
  114 + }
  115 +
  116 + }
  117 +
  118 +}
  119 +
  120 +
  121 +/// 导出视频
  122 ++ (void)getVideoWithAsset:(PHAsset *)asset outputPath:(NSString *)outputPath presetName:(NSString *)presetName success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure {
  123 +
  124 + PHVideoRequestOptions* options = [[PHVideoRequestOptions alloc] init];
  125 + options.version = PHVideoRequestOptionsVersionOriginal;
  126 + options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
  127 + options.networkAccessAllowed = YES;
  128 + [[PHImageManager defaultManager] requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset* avasset, AVAudioMix* audioMix, NSDictionary* info){
  129 + // NSLog(@"Info:\n%@",info);
  130 + AVURLAsset *videoAsset = (AVURLAsset*)avasset;
  131 + // NSLog(@"AVAsset URL: %@",myAsset.URL);
  132 + [PHAsset startExportVideoWithVideoAsset:videoAsset outputPath:outputPath presetName:presetName success:success failure:failure];
  133 + }];
  134 +}
  135 +
  136 ++ (void)startExportVideoWithVideoAsset:(AVURLAsset *)videoAsset outputPath:(NSString *)outputPath presetName:(NSString *)presetName success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure {
  137 +
  138 + NSArray *presets = [AVAssetExportSession exportPresetsCompatibleWithAsset:videoAsset];
  139 + if ([presets containsObject:presetName]) {
  140 + AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:videoAsset presetName:presetName];
  141 +
  142 + NSString *path = [NSString string];
  143 + if (outputPath.length <= 0 || outputPath) {
  144 + NSDateFormatter *formater = [[NSDateFormatter alloc] init];
  145 + [formater setDateFormat:@"yyyy-MM-dd-HH:mm:ss-SSS"];
  146 + path = [NSHomeDirectory() stringByAppendingFormat:@"/tmp/output-%@.mp4", [formater stringFromDate:[NSDate date]]];
  147 +
  148 + }else {
  149 + path = outputPath;
  150 + }
  151 +
  152 + // NSLog(@"video outputPath = %@",path);
  153 + session.outputURL = [NSURL fileURLWithPath:path];
  154 +
  155 + // Optimize for network use.
  156 + session.shouldOptimizeForNetworkUse = true;
  157 +
  158 + NSArray *supportedTypeArray = session.supportedFileTypes;
  159 + if ([supportedTypeArray containsObject:AVFileTypeMPEG4]) {
  160 + session.outputFileType = AVFileTypeMPEG4;
  161 + } else if (supportedTypeArray.count == 0) {
  162 + if (failure) {
  163 + failure(@"该视频类型暂不支持导出", nil);
  164 + }
  165 + NSLog(@"No supported file types 视频类型暂不支持导出");
  166 + return;
  167 + } else {
  168 + session.outputFileType = [supportedTypeArray objectAtIndex:0];
  169 + }
  170 +
  171 + if (![[NSFileManager defaultManager] fileExistsAtPath:[NSHomeDirectory() stringByAppendingFormat:@"/tmp"]]) {
  172 + [[NSFileManager defaultManager] createDirectoryAtPath:[NSHomeDirectory() stringByAppendingFormat:@"/tmp"] withIntermediateDirectories:YES attributes:nil error:nil];
  173 + }
  174 +
  175 + AVMutableVideoComposition *videoComposition = [PHAsset fixedCompositionWithAsset:videoAsset];
  176 + if (videoComposition.renderSize.width) {
  177 + // 修正视频转向
  178 + session.videoComposition = videoComposition;
  179 + }
  180 +
  181 + // Begin to export video to the output path asynchronously.
  182 + [session exportAsynchronouslyWithCompletionHandler:^(void) {
  183 + dispatch_async(dispatch_get_main_queue(), ^{
  184 + switch (session.status) {
  185 + case AVAssetExportSessionStatusUnknown: {
  186 + NSLog(@"AVAssetExportSessionStatusUnknown");
  187 + } break;
  188 + case AVAssetExportSessionStatusWaiting: {
  189 + NSLog(@"AVAssetExportSessionStatusWaiting");
  190 + } break;
  191 + case AVAssetExportSessionStatusExporting: {
  192 + NSLog(@"AVAssetExportSessionStatusExporting");
  193 + } break;
  194 + case AVAssetExportSessionStatusCompleted: {
  195 + NSLog(@"AVAssetExportSessionStatusCompleted");
  196 + if (success) {
  197 + success(outputPath);
  198 + }
  199 + } break;
  200 + case AVAssetExportSessionStatusFailed: {
  201 + NSLog(@"AVAssetExportSessionStatusFailed");
  202 + if (failure) {
  203 + failure(@"视频导出失败", session.error);
  204 + }
  205 + } break;
  206 + case AVAssetExportSessionStatusCancelled: {
  207 + NSLog(@"AVAssetExportSessionStatusCancelled");
  208 + if (failure) {
  209 + failure(@"导出任务已被取消", nil);
  210 + }
  211 + } break;
  212 + default: break;
  213 + }
  214 + });
  215 + }];
  216 + } else {
  217 + if (failure) {
  218 + NSString *errorMessage = [NSString stringWithFormat:@"当前设备不支持该预设:%@", presetName];
  219 + failure(errorMessage, nil);
  220 + }
  221 + }
  222 +}
  223 +
  224 +/// 获取优化后的视频转向信息
  225 ++ (AVMutableVideoComposition *)fixedCompositionWithAsset:(AVAsset *)videoAsset {
  226 + AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
  227 + // 视频转向
  228 + int degrees = [PHAsset degressFromVideoFileWithAsset:videoAsset];
  229 + if (degrees != 0) {
  230 + CGAffineTransform translateToCenter;
  231 + CGAffineTransform mixedTransform;
  232 + videoComposition.frameDuration = CMTimeMake(1, 30);
  233 +
  234 + NSArray *tracks = [videoAsset tracksWithMediaType:AVMediaTypeVideo];
  235 + AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
  236 +
  237 + AVMutableVideoCompositionInstruction *roateInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
  238 + roateInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, [videoAsset duration]);
  239 + AVMutableVideoCompositionLayerInstruction *roateLayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
  240 +
  241 + if (degrees == 90) {
  242 + // 顺时针旋转90°
  243 + translateToCenter = CGAffineTransformMakeTranslation(videoTrack.naturalSize.height, 0.0);
  244 + mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI_2);
  245 + videoComposition.renderSize = CGSizeMake(videoTrack.naturalSize.height,videoTrack.naturalSize.width);
  246 + [roateLayerInstruction setTransform:mixedTransform atTime:kCMTimeZero];
  247 + } else if(degrees == 180){
  248 + // 顺时针旋转180°
  249 + translateToCenter = CGAffineTransformMakeTranslation(videoTrack.naturalSize.width, videoTrack.naturalSize.height);
  250 + mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI);
  251 + videoComposition.renderSize = CGSizeMake(videoTrack.naturalSize.width,videoTrack.naturalSize.height);
  252 + [roateLayerInstruction setTransform:mixedTransform atTime:kCMTimeZero];
  253 + } else if(degrees == 270){
  254 + // 顺时针旋转270°
  255 + translateToCenter = CGAffineTransformMakeTranslation(0.0, videoTrack.naturalSize.width);
  256 + mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI_2*3.0);
  257 + videoComposition.renderSize = CGSizeMake(videoTrack.naturalSize.height,videoTrack.naturalSize.width);
  258 + [roateLayerInstruction setTransform:mixedTransform atTime:kCMTimeZero];
  259 + }
  260 +
  261 + roateInstruction.layerInstructions = @[roateLayerInstruction];
  262 + // 加入视频方向信息
  263 + videoComposition.instructions = @[roateInstruction];
  264 + }
  265 + return videoComposition;
  266 +}
  267 +
  268 +/// 获取视频角度
  269 ++ (int)degressFromVideoFileWithAsset:(AVAsset *)asset {
  270 + int degress = 0;
  271 + NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
  272 + if([tracks count] > 0) {
  273 + AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
  274 + CGAffineTransform t = videoTrack.preferredTransform;
  275 + if(t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0){
  276 + // Portrait
  277 + degress = 90;
  278 + } else if(t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0){
  279 + // PortraitUpsideDown
  280 + degress = 270;
  281 + } else if(t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0){
  282 + // LandscapeRight
  283 + degress = 0;
  284 + } else if(t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0){
  285 + // LandscapeLeft
  286 + degress = 180;
  287 + }
  288 + }
  289 + return degress;
  290 +}
  291 +
  292 +
  293 +
  294 +
  295 +
  296 +
  297 +
  298 +
  299 +@end
... ...
CNLiveUploadManager/压缩图片/UIImage+Luban_iOS_Extension_h.h renamed to CNLiveUploadManager/压缩图片/UIImage+Luban_iOS_Extension.h
... ... @@ -8,7 +8,7 @@
8 8  
9 9 #import <UIKit/UIKit.h>
10 10  
11   -@interface UIImage (Luban_iOS_Extension_h)
  11 +@interface UIImage (Luban_iOS_Extension)
12 12  
13 13 + (NSData *)lubanCompressImage:(UIImage *)image;//压缩图片
14 14 + (NSData *)lubanCompressImage:(UIImage *)image withMask:(NSString *)maskName;//水印
... ...
CNLiveUploadManager/压缩图片/UIImage+Luban_iOS_Extension_h.m renamed to CNLiveUploadManager/压缩图片/UIImage+Luban_iOS_Extension.m
... ... @@ -7,7 +7,7 @@
7 7 //
8 8  
9 9 #import <objc/runtime.h>
10   -#import "UIImage+Luban_iOS_Extension_h.h"
  10 +#import "UIImage+Luban_iOS_Extension.h"
11 11  
12 12 @implementation UIImage (Luban_iOS_Extension_h)
13 13  
... ...
CNLiveUploadManager/压缩图片/UIImage+zipData.h
... ... @@ -7,12 +7,6 @@
7 7 //
8 8  
9 9 #import <UIKit/UIKit.h>
10   -typedef NS_ENUM(NSUInteger, AppPhototLimitType) {
11   - AppPhototLimitTypeFriendsCircle = 0,//朋友圈图片限制20M
12   - AppPhototLimitTypeTarentoComment = 1,//达人评论图片限制10M
13   - AppPhototLimitTypeSweepCode = 2,//扫码图片限制10M
14   - AppPhototLimitTypeChat = 3,//聊天图片限制20M
15   -};
16 10  
17 11 @interface UIImage (zipData)
18 12  
... ...