Commit bd67be37868206f6aceecc856cf4f060b1071809

Authored by 梁星国
1 parent 706eb29e

tijiao

Showing 32 changed files with 2780 additions and 52 deletions
CNLiveUploadManager/CNLiveUploadManager.podspec renamed to CNLiveUploadManager.podspec
CNLiveUploadManager/.gitignore deleted 100644 → 0
1   -# OS X
2   -.DS_Store
3   -
4   -# Xcode
5   -build/
6   -*.pbxuser
7   -!default.pbxuser
8   -*.mode1v3
9   -!default.mode1v3
10   -*.mode2v3
11   -!default.mode2v3
12   -*.perspectivev3
13   -!default.perspectivev3
14   -xcuserdata/
15   -*.xccheckout
16   -profile
17   -*.moved-aside
18   -DerivedData
19   -*.hmap
20   -*.ipa
21   -
22   -# Bundler
23   -.bundle
24   -
25   -# Add this line if you want to avoid checking in source code from Carthage dependencies.
26   -# Carthage/Checkouts
27   -
28   -Carthage/Build
29   -
30   -# We recommend against adding the Pods directory to your .gitignore. However
31   -# you should judge for yourself, the pros and cons are mentioned at:
32   -# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
33   -#
34   -# Note: if you ignore the Pods directory, make sure to uncomment
35   -# `pod install` in .travis.yml
36   -#
37   -# Pods/
CNLiveUploadManager/.travis.yml deleted 100644 → 0
1   -# references:
2   -# * https://www.objc.io/issues/6-build-tools/travis-ci/
3   -# * https://github.com/supermarin/xcpretty#usage
4   -
5   -osx_image: xcode7.3
6   -language: objective-c
7   -# cache: cocoapods
8   -# podfile: Example/Podfile
9   -# before_install:
10   -# - gem install cocoapods # Since Travis is not always on latest version
11   -# - pod install --project-directory=Example
12   -script:
13   -- set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/CNLiveUploadManager.xcworkspace -scheme CNLiveUploadManager-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty
14   -- pod lib lint
CNLiveUploadManager/CNLiveUploadManager/Assets/.gitkeep renamed to CNLiveUploadManager/Assets/.gitkeep
CNLiveUploadManager/CNLiveUploadManager/Classes/ReplaceMe.m deleted 100644 → 0
CNLiveUploadManager/CNLiveUploadManager/Classes/.gitkeep renamed to CNLiveUploadManager/Classes/.gitkeep
CNLiveUploadManager/Classes/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 <Qiniu/QiniuSDK.h>
  11 +#import <Qiniu/QNUploadManager.h>
  12 +#import <UIKit/UIKit.h>
  13 +#import <AssetsLibrary/AssetsLibrary.h>
  14 +#import <PLShortVideoKit/PLShortVideoKit.h>
  15 +#import <Photos/Photos.h>
  16 +#import "QNResolver.h"
  17 +#import "QNDnsManager.h"
  18 +#import "QNNetworkInfo.h"
  19 +#import "UIImage+zipData.h"
  20 +
  21 +@class CNLiveUploadModel;
  22 +
  23 +#define kCNUploadSize10MB 10*1024*1024 //用于大于10MB的变为960*540分辨率
  24 +#define kCNUploadSize20MB 20*1024*1024 //用于大于20MB的变为960*540分辨率
  25 +#define kCNUploadSize30MB 30*1024*1024 //用于大于30MB的变为640*480分辨率
  26 +#define kCNUploadSize40MB 40*1024*1024 //用于大于40MB的变为640*480分辨率
  27 +#define kCNUploadSize50MB 50*1024*1024 //用于大于50MB的变为640*480分辨率
  28 +#define kCNUploadSize100MB 100*1024*1024 //用于大于100MB的变为640*480分辨率
  29 +
  30 +typedef NS_ENUM(NSUInteger, CNLiveUploadType) {
  31 + CNLiveUploadTypeQN,//七牛
  32 + CNLiveUploadTypeKS,//金山
  33 + CNLiveUploadTypeOther,//AF
  34 + CNLiveUploadTypeThird,//AF_第三方平台
  35 +};
  36 +
  37 +typedef enum : NSUInteger {
  38 + CNAssetModelMediaTypePhoto = 0,
  39 + CNAssetModelMediaTypeLivePhoto,
  40 + CNAssetModelMediaTypePhotoGif,
  41 + CNAssetModelMediaTypeVideo,
  42 + CNAssetModelMediaTypeAudio
  43 +} CNAssetModelMediaType;
  44 +
  45 +typedef void (^successBlock)(NSMutableArray* fileArray);//成功数组
  46 +typedef void (^failureBlock)(NSMutableArray* errorArray, NSError *error);//失败数组,错误
  47 +
  48 +typedef void (^successModelBlock)(CNLiveUploadModel *uploadModel);//成功数组
  49 +typedef void (^failureModelBlock)(CNLiveUploadModel *uploadModel, NSError *error);//失败数组,错误
  50 +
  51 +typedef void (^transcodeHandlerBlock)(float progress, BOOL isSuccess); //转码进度
  52 +typedef void (^progressHandlerBlock)(float progress);//进度
  53 +
  54 +@interface CNLiveUploadManager : NSObject
  55 +
  56 +
  57 +/**
  58 + 释放单例
  59 + */
  60 ++(void)attempDealloc;
  61 +
  62 +/**
  63 + 实例化
  64 + */
  65 ++(CNLiveUploadManager *)shareInsance;
  66 +
  67 +/// 单张上传NSData
  68 ++ (void)uploadType:(CNLiveUploadType)type token:(NSString*)token data:(NSData *)data progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure;
  69 +
  70 +///单张上传UIImage
  71 ++ (void)uploadType:(CNLiveUploadType)type token:(NSString*)token image:(UIImage *)image progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure;
  72 +
  73 +/// CNLive上传多张NSData
  74 ++ (void)uploadType:(CNLiveUploadType)type token:(NSString*)token dataArray:(NSMutableArray<NSData *> *)dataArray progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure;
  75 +
  76 +/// (视频)路径上传
  77 ++ (void)uploadVideoType:(CNLiveUploadType)type file:(NSString *)file token:(NSString *)token progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure;
  78 +
  79 +/// 单图上传 (asset取得Image - 压缩或原图 - 限制 - 筛选)
  80 ++ (void)uploadLimitType:(CNLiveUploadType)type phAsset:(PHAsset *)phAsset isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType token:(NSString *)token progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure;
  81 +
  82 +/// 单图上传 (Image - 压缩或原图 - 限制 - 筛选)
  83 ++ (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;
  84 +
  85 +/// 多张图上传 (images - 压缩或原图 - 限制 - 筛选)
  86 ++ (void)uploadLimitType:(CNLiveUploadType)type imageArray:(NSMutableArray *)imageArray assetArray:(NSMutableArray *)assetArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType token:(NSString *)token progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure;
  87 +
  88 +/// 多张图上传 (assetArray - 压缩 - 限制 - 筛选)
  89 ++ (void)uploadLimitType:(CNLiveUploadType)type token:(NSString *)token phAssetArray:(NSMutableArray<PHAsset *> *)phAssetArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure;
  90 +
  91 +/// 单个视频系统视频上传 (video - 压缩 - 限制 - 筛选)
  92 ++ (void)uploadLimitVideoType:(CNLiveUploadType)type token:(NSString *)token asset:(id)asset limitType:(AppPhototLimitType)limitType outputPath:(NSString *)outputPath progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure ;
  93 +
  94 +/// 请求token 单张上传 (asset - 压缩 - 限制 - 筛选)
  95 ++ (void)uploadRequestType:(CNLiveUploadType)type url:(NSString *)url dic:(NSDictionary *)dic phAsset:(id)phAsset isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure;
  96 +
  97 +/// 请求token 单图上传 (Image - 压缩或原图 - 限制 - 筛选)
  98 ++ (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;
  99 +
  100 +/// 请求token 多张图上传 (images - 压缩或原图 - 限制 - 筛选)
  101 ++ (void)uploadRequestType:(CNLiveUploadType)type url:(NSString *)url dic:(NSDictionary *)dic imageArray:(NSMutableArray *)imageArray assetArray:(NSMutableArray *)assetArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure;
  102 +
  103 +/// 请求token (assetArray - 压缩 - 限制 - 筛选)
  104 ++ (void)uploadRequestType:(CNLiveUploadType)type url:(NSString *)url dic:(NSDictionary *)dic phAssetArray:(NSMutableArray<PHAsset *> *)phAssetArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure;
  105 +
  106 +/// 请求token 单个视频上传 (video - 压缩 - 限制 - 筛选)
  107 ++ (void)uploadRequestVideoType:(CNLiveUploadType)type url:(NSString *)url dic:(NSDictionary *)dic asset:(id)asset limitType:(AppPhototLimitType)limitType outputPath:(NSString *)outputPath progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure;
  108 +
  109 +/// 请求token 单个视频上传 (video - 七牛短视频压缩 - 限制 - 筛选)
  110 ++ (void)uploadRequestWhithPLShortVideoType:(CNLiveUploadType)type outputPath:(NSString *)outputPath url:(NSString *)url dic:(NSDictionary *)dic asset:(id)asset limitType:(AppPhototLimitType)limitType transcode:(transcodeHandlerBlock) transcode progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure;
  111 +
  112 +/// 短视频分辨率转码导出
  113 ++ (void )zipVideoWithAsset:(id) asset outputPath:(NSString *)outputPath limitType:(AppPhototLimitType)limitType progressCount:(void(^)(float progress)) progressCount success:(void(^)(NSURL * url))success failure:(void(^)(void))failure;
  114 +
  115 +/// 新短视频分辨率转码导出
  116 ++ (void )zipNewVideoWithAsset:(id) asset outputPath:(NSString *)outputPath limitType:(AppPhototLimitType)limitType progressCount:(void(^)(float progress)) progressCount success:(void(^)(NSURL * url))success failure:(void(^)(void))failure;
  117 +
  118 +/// 根据限制获取视频分辨率
  119 ++ (PLSFilePreset)presetWithVideoLimitType:(AppPhototLimitType)limitType url:(NSURL *)url dataL:(float)dataL;
  120 +
  121 +///根据分辨力设置码率
  122 ++ (float)bitrateWithPreset:(PLSFilePreset)perset avAsset:(AVAsset *)avAsset url:(NSURL *)url dataL:(float)dataL;
  123 +
  124 +@end
  125 +
  126 +
  127 +
  128 +#pragma mark - CNLiveUploadModel
  129 +
  130 +@interface CNLiveUploadModel : NSObject
  131 +/** 状态码 */
  132 +@property (copy, nonatomic) NSString *code;
  133 +/** 索引 */
  134 +@property (assign, nonatomic) NSInteger index;
  135 +/** 图片路径 (视频,图片) */
  136 +@property (copy, nonatomic) NSString *imageUrl;
  137 +/** file */
  138 +@property (copy, nonatomic) NSString *file;
  139 +/** 消息 */
  140 +@property (copy, nonatomic) NSString *message;
  141 +/** 图片 */
  142 +@property (strong, nonatomic) UIImage *image;
  143 +/** imageW */
  144 +@property (assign, nonatomic) NSInteger imageW;
  145 +/** imageH */
  146 +@property (assign, nonatomic) NSInteger imageH;
  147 +/** CNAsset */
  148 +@property (strong, nonatomic) id asset;
  149 +
  150 +// 七牛回调参数
  151 +
  152 +@property (strong, nonatomic) QNResponseInfo *info;
  153 +
  154 +@property (copy, nonatomic) NSString *key;
  155 +
  156 +@property (copy, nonatomic) NSDictionary *resp;
  157 +
  158 +// 服务器参数
  159 +@property (strong, nonatomic) id responseObject;
  160 +
  161 +@end
  162 +
... ...
CNLiveUploadManager/Classes/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 "UIImage+zipData.h"
  11 +#import "CNLiveNetworking.h"
  12 +#import "CNLiveBusinessTools.h"
  13 +#import "CNUserInfoManager.h"
  14 +#import "CNUserInfoModel.h"
  15 +#import "CNLiveTimeTools.h"
  16 +#import "CNEnvironmentHeader.h"
  17 +#import "CNLiveNetworking.h"
  18 +#import "HttpService.h"
  19 +#import <AFNetworking/AFNetworking.h>
  20 +#import <YYKit/YYKit.h>
  21 +
  22 +
  23 +
  24 +#define kiOS9_1Later ([UIDevice currentDevice].systemVersion.floatValue >= 9.1f)
  25 +
  26 +
  27 +////////////////////////////////////////////////////////
  28 +//////////// 发送图片,视频限制
  29 +////////////////////////////////////////////////////////
  30 +#define kFriendsCircle_limit_photo 20*1024.0*1024.0 //朋友圈限制图片20M
  31 +#define kFirendsCircle_limit_video 30*1024.0*1024.0 //朋友圈限制视频30M
  32 +#define kTarentoComment_limit_photo 10*1024.0*1024.0 //达人评论10M
  33 +#define kSweepCode_limit_phoho 10*1024.0*1024.0 //扫码10M限制
  34 +#define kChat_limit_photo 20*1024.0*1024.0 //聊天限制图片20M
  35 +#define kChat_limit_video 20*1024.0*1024.0 //聊天限制视频20M
  36 +#define kChatBackgroupImage_limit_photo 5*1024.0*1024.0 //聊天背景图限制5 M
  37 +#define kChat_limit_video_length 5*60 //聊天限制视频5分钟
  38 +#define kFriendsCircle_limit_video_maxEdit 5*60 //朋友圈限制视频5分钟
  39 +#define kFriendsCircle_limit_video_max 10*60 //朋友圈限制最大视频编辑10分钟
  40 +
  41 +
  42 +
  43 +#pragma mark - 七牛category
  44 +
  45 +@implementation NSData(Qiniu)
  46 +
  47 +//获取图片格式
  48 +- (NSString *) imageFormatType{
  49 + uint8_t c;
  50 + [self getBytes:&c length:1];
  51 + switch (c) {
  52 + case 0xFF: return @".jpeg";
  53 + case 0x89: return @".png";
  54 + case 0x47: return @".gif";
  55 + case 0x49:
  56 + case 0x4D: return @".tiff";
  57 + default: return @".jpeg";
  58 + }
  59 + return nil;
  60 +}
  61 +
  62 +@end
  63 +
  64 +@implementation NSString(Qiniu)
  65 +/**
  66 + * 字符串判空
  67 + *
  68 + * @param string 需要判空的自字符串
  69 + * @return BOOL类型,YES为空字符
  70 + *
  71 + */
  72 ++ (BOOL)isEmpty:(NSString *)string {
  73 + return [string isEqual:[NSNull null]] || string == nil || string.length == 0;
  74 +}
  75 +
  76 +/**
  77 + 视频BucketKey,BucketKey为文件路径
  78 + */
  79 ++ (NSString *)getBucketKeyFromServerWithExt:(NSString *)ext
  80 +{
  81 + // @"82/wjj/video/TestUserUpload/2018/02/02/151754170779417093932.mp4"
  82 + NSString *spid = [CNLiveBusinessTools getSpid];
  83 + NSString *spBucketKey = [NSString stringWithFormat:@"%@/wjj/video",spid];
  84 + NSString *darenId = CNUserShareModel.uid;
  85 + NSString *yearTime = [CNLiveTimeTools getyyMMdd];//@"2018/02/02";//tools
  86 + NSString *timestampStr = [CNLiveTimeTools get13tsRandTimeStr];//@"151754170779417093932";//tools time+8rand
  87 + // NSString *ext = @"mp4";//mp4
  88 + NSString *bucketKey = [NSString stringWithFormat:@"%@/%@/%@/%@.%@",spBucketKey,darenId,yearTime,timestampStr,ext];
  89 + NSLog(@"bucketKey:%@",bucketKey);
  90 + return bucketKey;
  91 +}
  92 +
  93 +
  94 +// 图片的BucketKey,BuketKey为文件路径
  95 ++ (NSString *)getImageBuketkeyFromServerWithExt:(NSString *)ext{
  96 + NSString *spid = [CNLiveBusinessTools getSpid];
  97 + NSString *imgBucketKey = [NSString stringWithFormat:@"%@/img", spid];
  98 + NSString *yearTime = [CNLiveTimeTools getyyMMdd];
  99 + NSString *timeTampStr = [CNLiveTimeTools get13tsRandTimeStr];
  100 + NSString *bucketKey = [NSString stringWithFormat:@"%@/%@/%@%@",imgBucketKey,yearTime,timeTampStr,ext];
  101 + return bucketKey;
  102 +}
  103 +
  104 +
  105 +@end
  106 +
  107 +
  108 +@implementation PHAsset (Qiniu)
  109 +
  110 +- (NSURL *)movieURL {
  111 + __block NSURL *url = nil;
  112 +
  113 + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
  114 +
  115 + if (self.mediaType == PHAssetMediaTypeVideo) {
  116 + PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
  117 + options.version = PHVideoRequestOptionsVersionOriginal;
  118 + options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
  119 + options.networkAccessAllowed = YES;
  120 +
  121 + PHImageManager *manager = [PHImageManager defaultManager];
  122 + [manager requestAVAssetForVideo:self options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
  123 + AVURLAsset *urlAsset = (AVURLAsset *)asset;
  124 + url = urlAsset.URL;
  125 +
  126 + dispatch_semaphore_signal(semaphore);
  127 + }];
  128 + }
  129 +
  130 + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
  131 +
  132 + return url;
  133 +}
  134 +
  135 +- (NSData *)gifData {
  136 +
  137 + __block NSData *data = nil;
  138 + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
  139 +
  140 + PHImageManager *imageManager = [PHImageManager defaultManager];
  141 + PHImageRequestOptions *options = [PHImageRequestOptions new];
  142 + options.deliveryMode = PHImageRequestOptionsDeliveryModeFastFormat;
  143 + options.resizeMode = PHImageRequestOptionsResizeModeFast;
  144 + // options.synchronous = NO;
  145 + options.networkAccessAllowed = YES;
  146 + [imageManager requestImageDataForAsset:self options:options resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
  147 +
  148 + data = imageData;
  149 + dispatch_semaphore_signal(semaphore);
  150 +
  151 + }];
  152 + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
  153 +
  154 + return data;
  155 +
  156 +}
  157 +
  158 +
  159 +- (UIImage *)imageURL:(PHAsset *)phAsset targetSize:(CGSize)targetSize {
  160 + __block UIImage *image = nil;
  161 +
  162 + PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
  163 + options.networkAccessAllowed = YES;
  164 + options.synchronous = YES;
  165 +
  166 + // 设置 resizeMode = PHImageRequestOptionsResizeModeExact, 否则返回的图片大小不一定是设置的 targetSize
  167 + options.resizeMode = PHImageRequestOptionsResizeModeExact;
  168 +
  169 + // 设置 deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat,是保证 resultHandler 值回调一次,否则可能回回调多次,只有最后一次返回的图片大小等于设置的 targetSize
  170 + options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
  171 +
  172 + PHImageManager *manager = [PHImageManager defaultManager];
  173 + [manager requestImageForAsset:phAsset targetSize:targetSize contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
  174 + image = result;
  175 + }];
  176 +
  177 + return image;
  178 +}
  179 +
  180 +
  181 +- (NSURL *)getImageFilePath {
  182 +
  183 + NSString *cacheFolder = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
  184 + NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
  185 + formatter.dateFormat = @"yyyyMMddHHmmssSSS";
  186 + NSString *nowTimeStr = [formatter stringFromDate:[NSDate dateWithTimeIntervalSinceNow:0]];
  187 + NSString *urlString = [NSString stringWithFormat:@"%@/%@.JPG", cacheFolder, nowTimeStr];
  188 + return [NSURL fileURLWithPath:urlString];
  189 +
  190 +}
  191 +
  192 +- (NSURL *)getImageURL:(PHAsset *)phAsset {
  193 +
  194 + PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
  195 + options.networkAccessAllowed = YES;
  196 + options.synchronous = YES;
  197 +
  198 + PHImageManager *manager = [PHImageManager defaultManager];
  199 + __block NSURL *url = nil;
  200 + __weak typeof(self) wself = self;
  201 + [manager requestImageDataForAsset:phAsset options:options resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
  202 + if (imageData) {
  203 + // 这里需要重新将图片数据写到 App 可以访问的目录,不然直接使用 info 中的 url,可能会获取不到图片数据
  204 + url = [wself getImageFilePath];
  205 + [[NSFileManager defaultManager] createFileAtPath:url.path contents:imageData attributes:nil];
  206 + }
  207 + }];
  208 +
  209 + return url;
  210 +}
  211 +
  212 +@end
  213 +
  214 +
  215 +#pragma mark -
  216 +#pragma mark - CNLiveUploadManager
  217 +
  218 +@interface CNLiveUploadManager ()
  219 +
  220 +@property (nonatomic, strong) QNUploadManager *qnUploadManager;
  221 +
  222 +
  223 +@end
  224 +
  225 +@implementation CNLiveUploadManager
  226 +
  227 +static CNLiveUploadManager *_uploadManager;
  228 +/// 实例化
  229 ++(CNLiveUploadManager *)shareInsance{
  230 + static dispatch_once_t onceToken;
  231 + dispatch_once(&onceToken, ^{
  232 + _uploadManager = [[CNLiveUploadManager alloc] init];
  233 + });
  234 + return _uploadManager;
  235 +}
  236 +
  237 +/// 初始化
  238 +- (instancetype)init {
  239 + self = [super init];
  240 + if (self) {
  241 + // 配置信息
  242 + QNConfiguration *config = [QNConfiguration build:^(QNConfigurationBuilder *builder) {
  243 + builder.useHttps = YES;
  244 + //设置断点续传
  245 + NSError *error;
  246 + builder.recorder = [QNFileRecorder fileRecorderWithFolder:@"网++" error:&error];
  247 + }];
  248 + _qnUploadManager = [[QNUploadManager alloc] initWithConfiguration:config];
  249 +
  250 + }
  251 + return self;
  252 +}
  253 +
  254 +/// 释放
  255 ++(void)attempDealloc {
  256 + if (_uploadManager) {
  257 + _uploadManager = nil;
  258 + }
  259 +
  260 +}
  261 +
  262 +#pragma mark - 基础上传一层
  263 +/// 单张上传 - NSData
  264 +- (void)qnUploadWithToken:( NSString* )token data:(NSData * _Nonnull)data key:(NSString *)key progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  265 +
  266 + //上传
  267 + NSString *total = [NSString stringWithFormat:@"1"];
  268 + NSString *current = [NSString stringWithFormat:@"1"];
  269 + NSDictionary *dic = @{
  270 + @"x:total":total,
  271 + @"x:current":current
  272 + }.copy;
  273 +
  274 + QNUploadOption *opt = [[QNUploadOption alloc] initWithMime:nil progressHandler:^(NSString *key, float percent) {
  275 +
  276 + !progress ? : progress(percent);
  277 + } params:dic checkCrc:YES cancellationSignal:nil];
  278 +
  279 + [_qnUploadManager putData:data key:key token:token complete:^(QNResponseInfo *info, NSString *key, NSDictionary *resp) {
  280 +
  281 + dispatch_async(dispatch_get_main_queue(), ^{
  282 +
  283 + //返回结果
  284 + if (info.ok) {//成功
  285 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  286 + uploadModel.info = info;
  287 + uploadModel.key = key;
  288 + uploadModel.resp = resp;
  289 +
  290 + uploadModel.code = @"200";
  291 + uploadModel.index = 1;
  292 + uploadModel.imageUrl = [NSString stringWithFormat:@"%@%@",API_PhotoUrl,key];
  293 + uploadModel.message = @"上传成功";
  294 + uploadModel.image = [UIImage imageWithData:data];
  295 + uploadModel.imageW = uploadModel.image.size.width;
  296 + uploadModel.imageH = uploadModel.image.size.height;
  297 +
  298 + !success ? : success(uploadModel);
  299 +
  300 + }else{//失败
  301 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  302 + uploadModel.info = info;
  303 + uploadModel.key = key;
  304 + uploadModel.resp = resp;
  305 +
  306 + uploadModel.code = @"400";
  307 + uploadModel.index = 1;
  308 + uploadModel.imageUrl = @"";
  309 + uploadModel.message = @"上传失败";
  310 + uploadModel.image = [UIImage imageWithData:data];
  311 + uploadModel.imageW = uploadModel.image.size.width;
  312 + uploadModel.imageH = uploadModel.image.size.height;
  313 +
  314 + !failure ? : failure(uploadModel,info.error);
  315 + }
  316 + });
  317 +
  318 + } option:opt];
  319 +
  320 +}
  321 +
  322 +///单PHAsset上传 - PHAsset
  323 +- (void)qnUploadWithToken:(NSString*)token phAsset:(PHAsset *)phAsset key:(NSString *)key progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  324 +
  325 + //上传
  326 + NSString *total = [NSString stringWithFormat:@"1"];
  327 + NSString *current = [NSString stringWithFormat:@"1"];
  328 + NSDictionary *dic = @{
  329 + @"x:total":total,
  330 + @"x:current":current
  331 + }.copy;
  332 + __block CGFloat currentPresent =0;//当前进度
  333 + QNUploadOption *opt = [[QNUploadOption alloc] initWithMime:nil progressHandler:^(NSString *key, float percent) {
  334 + currentPresent += percent;
  335 + NSLog(@"输出个数%f",currentPresent);//单个视频的进度
  336 + !progress ? : progress(currentPresent);
  337 + } params:dic checkCrc:YES cancellationSignal:nil];
  338 +
  339 + [_qnUploadManager putPHAsset:phAsset key:key token:token complete:^(QNResponseInfo *info, NSString *key, NSDictionary *resp) {
  340 + dispatch_async(dispatch_get_main_queue(), ^{
  341 + //返回结果
  342 + if (info.ok) {//成功
  343 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  344 + uploadModel.info = info;
  345 + uploadModel.key = key;
  346 + uploadModel.resp = resp;
  347 +
  348 + uploadModel.code = @"200";
  349 + uploadModel.index = 1;
  350 + uploadModel.asset = phAsset;
  351 + uploadModel.imageUrl = [NSString stringWithFormat:@"%@%@",API_PhotoUrl,key];
  352 + uploadModel.message = @"上传成功";
  353 +
  354 + !success ? : success(uploadModel);
  355 +
  356 + }else{//失败
  357 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  358 + uploadModel.info = info;
  359 + uploadModel.key = key;
  360 + uploadModel.resp = resp;
  361 +
  362 + uploadModel.code = @"103";
  363 + uploadModel.index = 1;
  364 + uploadModel.imageUrl = @"";
  365 + uploadModel.message = @"上传失败";
  366 +
  367 + !failure ? : failure(uploadModel,info.error);
  368 +
  369 + }
  370 + });
  371 +
  372 + } option:opt];
  373 +
  374 +}
  375 +
  376 +/// (视频)单file上传 - file
  377 +- (void)qnUploadVideoWithToken:(NSString*)token file:(NSString *)file key:(NSString *)key progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  378 + //上传
  379 + NSString *total = [NSString stringWithFormat:@"1"];
  380 + NSString *current = [NSString stringWithFormat:@"1"];
  381 + NSDictionary *dic = @{
  382 + @"x:total":total,
  383 + @"x:current":current
  384 + }.copy;
  385 +
  386 + QNUploadOption *opt = [[QNUploadOption alloc] initWithMime:nil progressHandler:^(NSString *key, float percent) {
  387 +
  388 + NSLog(@"输出个数%f",percent);//单个视频的进度
  389 + !progress ? : progress(percent);
  390 + } params:dic checkCrc:YES cancellationSignal:nil];
  391 +
  392 + [_qnUploadManager putFile:file key:key token:token complete:^(QNResponseInfo *info, NSString *key, NSDictionary *resp) {
  393 + dispatch_async(dispatch_get_main_queue(), ^{
  394 + //返回结果
  395 + if (info.ok) {//成功
  396 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  397 + uploadModel.info = info;
  398 + uploadModel.key = key;
  399 + uploadModel.resp = resp;
  400 +
  401 + uploadModel.code = @"200";
  402 + uploadModel.index = 1;
  403 + uploadModel.file = file;
  404 + uploadModel.imageUrl = [NSString stringWithFormat:@"%@%@",API_PhotoUrl,key];
  405 + uploadModel.file = file;
  406 + uploadModel.message = @"上传成功";
  407 +
  408 + !success ? : success(uploadModel);
  409 +
  410 + }else{//失败
  411 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  412 + uploadModel.info = info;
  413 + uploadModel.key = key;
  414 + uploadModel.resp = resp;
  415 +
  416 + uploadModel.code = @"400";
  417 + uploadModel.index = 1;
  418 + uploadModel.imageUrl = @"";
  419 + uploadModel.file = file;
  420 + uploadModel.message = @"上传失败";
  421 +
  422 + !failure ? : failure(uploadModel,info.error);
  423 + }
  424 + });
  425 +
  426 + } option:opt];
  427 +
  428 +}
  429 +
  430 +/// 多张上传 - NSData - 排序
  431 +- (void)qnUploadWithToken:(NSString*)token dataArray:(NSMutableArray<NSData *> *)dataArr keys:(NSMutableArray<NSString *>*)keys progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  432 +
  433 + //上传图片数组
  434 + if (dataArr.count != keys.count) {
  435 + NSError *error = [NSError errorWithDomain:@"图片数和路径数不等" code:102 userInfo:@{NSLocalizedDescriptionKey:@"图片数和路径数不等,请重新获取"}];
  436 + !failure ? : failure(nil,error);
  437 + return;
  438 + }
  439 +
  440 + //回调数组
  441 + NSMutableArray *fileArray = [NSMutableArray array];//成功数组 CNLiveUploadModel
  442 + NSMutableArray *errorArray = [NSMutableArray array];//失败数组 CNLiveUploadModel
  443 + __block float count = 0;//进度
  444 +
  445 + //获得全局并发队列
  446 + dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  447 + //创建group
  448 + dispatch_group_t group = dispatch_group_create();
  449 + //GCD遍历图片数组
  450 + __weak __typeof(_qnUploadManager)weakManager = _qnUploadManager;
  451 + dispatch_apply(dataArr.count, globalQueue, ^(size_t index) {
  452 + dispatch_group_enter(group);
  453 + __strong __typeof(weakManager)strongManager = weakManager;
  454 +
  455 + //上传
  456 + NSString *total = [NSString stringWithFormat:@"%ld",(unsigned long)dataArr.count];
  457 + NSString *current = [NSString stringWithFormat:@"%ld",index+1];
  458 + NSDictionary *dic = @{
  459 + @"x:total":total,
  460 + @"x:current":current
  461 + }.copy;
  462 + QNUploadOption *opt = [[QNUploadOption alloc] initWithMime:nil progressHandler:^(NSString *key, float percent) {
  463 +
  464 + } params:dic checkCrc:YES cancellationSignal:nil];
  465 +
  466 + [strongManager putData:dataArr[index] key:keys[index] token:token complete:^(QNResponseInfo *info, NSString *key, NSDictionary *resp) {
  467 +
  468 + NSLog(@"***输出第%zi图片***",index);
  469 + //进度
  470 + count ++;
  471 + float progressCount = count / dataArr.count;
  472 + !progress ? : progress(progressCount);
  473 +
  474 + //返回结果
  475 + if (info.ok) {//成功
  476 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  477 + uploadModel.info = info;
  478 + uploadModel.key = key;
  479 + uploadModel.resp = resp;
  480 +
  481 + uploadModel.code = @"200";
  482 + uploadModel.index = index;
  483 + uploadModel.imageUrl = [NSString stringWithFormat:@"%@%@",API_PhotoUrl,key];
  484 + uploadModel.message = @"上传成功";
  485 + uploadModel.image = [UIImage imageWithData:dataArr[index]];
  486 + uploadModel.imageW = uploadModel.image.size.width;
  487 + uploadModel.imageH = uploadModel.image.size.height;
  488 + [fileArray addObject:uploadModel];
  489 +
  490 + }else{//失败
  491 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  492 + uploadModel.info = info;
  493 + uploadModel.key = key;
  494 + uploadModel.resp = resp;
  495 +
  496 + uploadModel.code = @"400";
  497 + uploadModel.index = index;
  498 + uploadModel.imageUrl = @"";
  499 + uploadModel.message = @"上传失败";
  500 + uploadModel.image = [UIImage imageWithData:dataArr[index]];
  501 + uploadModel.imageW = uploadModel.image.size.width;
  502 + uploadModel.imageH = uploadModel.image.size.height;
  503 + [errorArray addObject:uploadModel];
  504 +
  505 + }
  506 +
  507 + dispatch_group_leave(group);
  508 +
  509 + } option:opt];
  510 +
  511 + });
  512 +
  513 + //group内的任务完成通知
  514 + dispatch_group_notify(group, dispatch_get_main_queue(), ^{
  515 +
  516 + if (dataArr.count == fileArray.count) {
  517 + //排序
  518 + [fileArray sortUsingComparator:^NSComparisonResult(CNLiveUploadModel * _Nonnull obj1, CNLiveUploadModel * _Nonnull obj2) {
  519 + if (obj1.index > obj2.index)
  520 + {
  521 + return NSOrderedDescending;
  522 + }
  523 + else
  524 + {
  525 + return NSOrderedAscending;
  526 + }
  527 + }];
  528 + !success ? : success(fileArray);
  529 + }else{
  530 +// !success ? : success(fileArray);
  531 + NSError *error = [NSError errorWithDomain:@"上传出现错误" code:400 userInfo:@{NSLocalizedDescriptionKey:@"上传出现错误,请重新上传失败图片"}];
  532 + !failure ? : failure(errorArray,error);
  533 + }
  534 +
  535 + });
  536 +
  537 +}
  538 +
  539 +#pragma mark - 简单上传二层 添加Key
  540 +/// 单张NSData上传 - Key
  541 +-(void)qnUploadWithToken:(NSString*)token data:(NSData *)data progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure{
  542 +
  543 + //初始化上传需要的参数
  544 + //imageKey获取x
  545 + NSString *key = [NSString getImageBuketkeyFromServerWithExt:[data imageFormatType]];
  546 +
  547 + [self qnUploadWithToken:token data:data key:key progress:progress success:success failure:failure];
  548 +
  549 +}
  550 +
  551 +/// 单张上传 - Key - 压缩
  552 +-(void)qnUploadWithToken:(NSString*)token image:(UIImage *)image progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure{
  553 +
  554 + //初始化上传需要的参数
  555 + //imageData转换,压缩
  556 + NSData *data = [UIImage zipNSDataWithImage:image];
  557 + //imageKey获取
  558 + NSString *key = [NSString getImageBuketkeyFromServerWithExt:[data imageFormatType]];
  559 +
  560 + [self qnUploadWithToken:token data:data key:key progress:progress success:success failure:failure];
  561 +
  562 +}
  563 +
  564 +/// 单张PHAsset上传
  565 +- (void)qnUploadWithToken:(NSString*)token phAsset:(PHAsset *)phAsset progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  566 +
  567 +
  568 + //七牛token
  569 + if ([NSString isEmpty:token]) {
  570 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  571 + !failure ? : failure(nil,error);
  572 + return;
  573 + }
  574 +
  575 + //上传路径
  576 + if (phAsset) {
  577 + NSError *error = [NSError errorWithDomain:@"上传路径为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"上传为空,请重新获取"}];
  578 + !failure ? : failure(nil,error);
  579 + return;
  580 + }
  581 +
  582 + //初始化上传需要的参数
  583 + NSString *key = [NSString string];
  584 + if ([self getAssetType:phAsset] == CNAssetModelMediaTypePhotoGif) {
  585 + key = [NSString stringWithFormat:@"%@",[NSString getImageBuketkeyFromServerWithExt:@".gif"]];
  586 + }else{
  587 + key = [NSString stringWithFormat:@"%@",[NSString getImageBuketkeyFromServerWithExt:@".jpg"]];
  588 + }
  589 +
  590 + [self qnUploadWithToken:token phAsset:phAsset key:key progress:progress success:success failure:failure];
  591 +}
  592 +
  593 +/// 多张图片dataArray上传 - Key
  594 +- (void)qnUploadWithToken:(NSString*)token dataArray:(NSMutableArray<NSData *> *)dataArray progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  595 +
  596 + //七牛token
  597 + if ([NSString isEmpty:token]) {
  598 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  599 + !failure ? : failure(nil,error);
  600 + return;
  601 + }
  602 +
  603 + //上传图片数组
  604 + if (dataArray.count <= 0) {
  605 + NSError *error = [NSError errorWithDomain:@"图片Data数组为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"图片Data数组为空,请重新获取"}];
  606 + !failure ? : failure(nil,error);
  607 + return;
  608 + }
  609 +
  610 + //初始化上传需要的参数
  611 + NSMutableArray *keyArray = @[].mutableCopy;
  612 + for (int i = 0; i < dataArray.count; i++) {
  613 +
  614 + NSString *key = [NSString getImageBuketkeyFromServerWithExt:[dataArray[i] imageFormatType]];
  615 + [keyArray addObject:key];
  616 + }
  617 +
  618 + [self qnUploadWithToken:token dataArray:dataArray keys:keyArray progress:progress success:success failure:failure];
  619 +
  620 +}
  621 +
  622 +
  623 +/// 视频路径上传 - key
  624 +- (void)qnUploadVideoWithToken:(NSString*)token file:(NSString *)file progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  625 +
  626 + //七牛token
  627 + if ([NSString isEmpty:token]) {
  628 + dispatch_async(dispatch_get_main_queue(), ^{
  629 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  630 + !failure ? : failure(nil,error);
  631 + return;
  632 + });
  633 + }
  634 +
  635 + //上传路径
  636 + if ([NSString isEmpty:file]) {
  637 +
  638 + dispatch_async(dispatch_get_main_queue(), ^{
  639 + NSError *error = [NSError errorWithDomain:@"上传路径为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"上传路径为空,请重新获取"}];
  640 + !failure ? : failure(nil,error);
  641 + return;
  642 + });
  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 +#pragma mark -- 七牛
  656 +///单张asset - asset取得Image - 压缩或原图 - 限制 - 筛选 实现
  657 +- (void)qnUploadLimitWithToken:(NSString*)token phAsset:(PHAsset *)phAsset isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  658 +
  659 + //七牛token
  660 + if ([NSString isEmpty:token]) {
  661 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  662 + !failure ? : failure(nil,error);
  663 + return;
  664 + }
  665 +
  666 + //上传路径
  667 + if (!phAsset) {
  668 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  669 + !failure ? : failure(nil,error);
  670 + return;
  671 + }
  672 +
  673 + //压缩
  674 + [self zipAsset:phAsset isOriginal:isOriginal success:^(NSData *data) {
  675 + //去空
  676 + if (!data) {
  677 + NSError *error = [NSError errorWithDomain:@"图片转码失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"图片转码失败,请重新获取"}];
  678 + !failure ? : failure(nil,error);
  679 + return;
  680 + }
  681 +
  682 + //筛选
  683 + if ([self isImageLimitType:limitType data:data]) {
  684 + [self qnUploadWithToken:token data:data progress:progress success:success failure:failure];
  685 + }else {
  686 + NSError *error = [NSError errorWithDomain:@"图片过大" code:104 userInfo:@{NSLocalizedDescriptionKey:@"图片过大,请重新获取"}];
  687 + !failure ? : failure(nil,error);
  688 + return;
  689 + }
  690 +
  691 + } failure:^{
  692 +
  693 + NSError *error = [NSError errorWithDomain:@"图片转码失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"图片转码失败,请重新获取"}];
  694 + !failure ? : failure(nil,error);
  695 + return;
  696 +
  697 + }];
  698 +
  699 +}
  700 +
  701 +///单张image - Image - 压缩或原图 - 限制 - 筛选) 实现
  702 +- (void)qnUploadLimitWithToken:(NSString*)token image:(UIImage *)image isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  703 +
  704 + //七牛token
  705 + if ([NSString isEmpty:token]) {
  706 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  707 + !failure ? : failure(nil,error);
  708 + return;
  709 + }
  710 +
  711 + //上传路径
  712 + if (!image) {
  713 + NSError *error = [NSError errorWithDomain:@"图片为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"图片为空,请重新获取"}];
  714 + !failure ? : failure(nil,error);
  715 + return;
  716 + }
  717 +
  718 + UIImage *origionImg = image;
  719 + if (origionImg) {
  720 + NSData *data = nil;
  721 + if (isOriginal) {
  722 + if (UIImageJPEGRepresentation(origionImg, 1.0)) {
  723 + data = UIImageJPEGRepresentation(origionImg, 1.0);
  724 + }else {
  725 + data = UIImagePNGRepresentation(origionImg);
  726 + }
  727 + }else{
  728 + data = [UIImage zipNSDataWithImage:origionImg];//压缩
  729 + }
  730 +
  731 + //去空
  732 + if (!data) {
  733 + NSError *error = [NSError errorWithDomain:@"图片为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"图片为空,请重新获取"}];
  734 + !failure ? : failure(nil,error);
  735 + return;
  736 + }
  737 +
  738 + //筛选
  739 + if ([self isImageLimitType:limitType data:data]) {
  740 + [self qnUploadWithToken:token data:data progress:progress success:success failure:failure];
  741 + }else{
  742 + NSError *error = [NSError errorWithDomain:@"图片过大" code:104 userInfo:@{NSLocalizedDescriptionKey:@"图片过大,请重新获取"}];
  743 + !failure ? : failure(nil,error);
  744 + return;
  745 +
  746 + }
  747 +
  748 + }else{
  749 + NSError *error = [NSError errorWithDomain:@"图片转码失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"图片转码失败,请重新获取"}];
  750 + !failure ? : failure(nil,error);
  751 + return;
  752 + }
  753 +
  754 +}
  755 +
  756 +/// 多张Assets上传 - Images - 压缩或原图 - 限制 - 筛选
  757 +- (void)qnUploadLimitWithToken:(NSString*)token phAssetArray:(NSMutableArray<PHAsset *> *)phAssetArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  758 +
  759 + //七牛token
  760 + if ([NSString isEmpty:token]) {
  761 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  762 + !failure ? : failure(nil,error);
  763 + return;
  764 + }
  765 +
  766 + //上传路径
  767 + if (phAssetArray.count <= 0) {
  768 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  769 + !failure ? : failure(nil,error);
  770 + return;
  771 + }
  772 +
  773 + //回调数组
  774 + NSMutableArray *fileArray = [NSMutableArray array];//成功数组 CNLiveUploadModel
  775 + NSMutableArray *errorArray = [NSMutableArray array];//失败数组 CNLiveUploadModel
  776 + //获得全局并发队列
  777 + dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  778 + //创建group
  779 + dispatch_group_t group = dispatch_group_create();
  780 +
  781 + //GCD遍历图片数组
  782 + NSInteger count = phAssetArray.count;
  783 + //进度
  784 + __block NSInteger progressCount = 0;
  785 + __weak typeof(self) weakSelf = self;
  786 +
  787 + dispatch_apply(count, globalQueue, ^(size_t index) {
  788 + __strong typeof(weakSelf) strongSelf = weakSelf;
  789 +
  790 + progressCount ++;//计数
  791 +
  792 + id asset = phAssetArray[index];
  793 + if (!asset) {
  794 +
  795 + !progressCount ? : progress(progressCount/phAssetArray.count);
  796 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  797 + !failure ? : failure(nil,error);
  798 + return;
  799 + }
  800 +
  801 + //压缩
  802 + dispatch_group_enter(group);
  803 + [strongSelf zipAsset:asset isOriginal:isOriginal success:^(NSData *data) {
  804 + //筛选
  805 + if ([strongSelf isImageLimitType:limitType data:data]) {
  806 +
  807 + [strongSelf qnUploadWithToken:token data:data progress:progress success:^(CNLiveUploadModel *uploadModel) {
  808 + uploadModel.index = index;
  809 + [fileArray addObject:uploadModel];
  810 + !progressCount ? : progress(progressCount/phAssetArray.count);
  811 +
  812 + dispatch_group_leave(group);
  813 + } failure:^(CNLiveUploadModel *uploadModel, NSError *error) {
  814 + uploadModel.index = index;
  815 + [errorArray addObject:uploadModel];
  816 + !progressCount ? : progress(progressCount/phAssetArray.count);
  817 +
  818 + dispatch_group_leave(group);
  819 + }];
  820 + }else {
  821 + !progressCount ? : progress(progressCount/phAssetArray.count);
  822 +
  823 + dispatch_group_leave(group);
  824 + }
  825 +
  826 + } failure:^{
  827 + !progressCount ? : progress(progressCount/phAssetArray.count);
  828 +
  829 + dispatch_group_leave(group);
  830 +
  831 + }];
  832 +
  833 + });
  834 +
  835 + //group内的任务完成通知
  836 + dispatch_group_notify(group, dispatch_get_main_queue(), ^{
  837 +
  838 + if (phAssetArray.count == fileArray.count) {
  839 + //排序
  840 + [fileArray sortUsingComparator:^NSComparisonResult(CNLiveUploadModel * _Nonnull obj1, CNLiveUploadModel * _Nonnull obj2) {
  841 + if (obj1.index > obj2.index)
  842 + {
  843 + return NSOrderedDescending;
  844 + }
  845 + else
  846 + {
  847 + return NSOrderedAscending;
  848 + }
  849 + }];
  850 + !success ? : success(fileArray);
  851 + }else{
  852 +// !success ? : success(fileArray);
  853 + NSError *error = [NSError errorWithDomain:@"上传出现错误" code:400 userInfo:@{NSLocalizedDescriptionKey:@"上传出现错误,请重新上传失败图片"}];
  854 + !failure ? : failure(errorArray,error);
  855 + }
  856 +
  857 + });
  858 +
  859 +}
  860 +
  861 +
  862 +///多张ImageArray + PHAssetArray - Images - 压缩或原图 - 限制 - 筛选(只对GiF进行导出,image直接压缩发了)
  863 +- (void)qnUploadLimitWithToken:(NSString*)token imageArray:(NSMutableArray<UIImage *> *)imageArray assetArray:(NSMutableArray *)assetArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  864 +
  865 + //七牛token
  866 + if ([NSString isEmpty:token]) {
  867 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  868 + !failure ? : failure(nil,error);
  869 + return;
  870 + }
  871 +
  872 + //上传路径
  873 + if (imageArray.count <= 0) {
  874 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  875 + !failure ? : failure(nil,error);
  876 + return;
  877 + }
  878 +
  879 + NSMutableArray *uploadDataArray = [NSMutableArray array];
  880 +
  881 + dispatch_queue_t queue = dispatch_queue_create("upload", DISPATCH_QUEUE_SERIAL);
  882 +
  883 + if (assetArray.count != imageArray.count) {
  884 + for (int i = 0; i < imageArray.count; i++) {
  885 + //编辑
  886 + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  887 + dispatch_sync(queue, ^{
  888 + //压缩
  889 + NSData *data = nil;
  890 + if (isOriginal) {
  891 + if (UIImageJPEGRepresentation(imageArray[i], 1.0)) {
  892 + data = UIImageJPEGRepresentation(imageArray[i], 1.0);
  893 + }else {
  894 + data = UIImagePNGRepresentation(imageArray[i]);
  895 + }
  896 + }else{
  897 + data = [UIImage zipNSDataWithImage:imageArray[i]];//压缩
  898 + }
  899 + [uploadDataArray addObject:data];
  900 + if (i == imageArray.count - 1) {
  901 + /// 上传DataArray
  902 + [self qnUploadWithToken:token dataArray:uploadDataArray progress:progress success:success failure:failure];
  903 + }
  904 +
  905 + });
  906 + });
  907 +
  908 + }
  909 +
  910 + }else {
  911 +
  912 + // 编辑
  913 + for (int i = 0; i < imageArray.count; i++) {
  914 + //编辑
  915 + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  916 + dispatch_sync(queue, ^{
  917 +
  918 + [self zipAsset:assetArray[i] image:imageArray[i] isOriginal:isOriginal success:^(NSData *data) {
  919 + [uploadDataArray addObject:data];
  920 + if (i == imageArray.count - 1) {
  921 + /// 上传DataArray
  922 + [self qnUploadWithToken:token dataArray:uploadDataArray progress:progress success:success failure:failure];
  923 + }
  924 +
  925 + }];
  926 +
  927 + });
  928 + });
  929 + }
  930 + }
  931 +
  932 +
  933 +}
  934 +
  935 +///单个视频系统导出上传 - 压缩或原图 - 限制 - 筛选) 实现
  936 +- (void)qnUploadVideoLimitWithToken:(NSString*)token asset:(id)asset limitType:(AppPhototLimitType)limitType outputPath:(NSString *)outputPath progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  937 +
  938 + //七牛token
  939 + if ([NSString isEmpty:token]) {
  940 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  941 + !failure ? : failure(nil,error);
  942 + return;
  943 + }
  944 +
  945 + //上传路径
  946 + if (!asset) {
  947 + NSError *error = [NSError errorWithDomain:@"上传路径为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"上传为空,请重新获取"}];
  948 + !failure ? : failure(nil,error);
  949 + return;
  950 + }
  951 +
  952 + PHVideoRequestOptions* options = [[PHVideoRequestOptions alloc] init];
  953 + options.version = PHVideoRequestOptionsVersionOriginal;
  954 + options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
  955 + options.networkAccessAllowed = YES;
  956 + options.progressHandler = ^(double progress, NSError * _Nullable error, BOOL * _Nonnull stop, NSDictionary * _Nullable info) {
  957 + NSLog(@"输出进度 = %f",progress);
  958 +
  959 + };
  960 + __weak typeof(self) weakSelf = self;
  961 + [[PHImageManager defaultManager] requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset* avasset, AVAudioMix* audioMix, NSDictionary* info){
  962 + __strong typeof(weakSelf) strongSelf = weakSelf;
  963 + if (!strongSelf) {
  964 + NSError *returnError = [NSError errorWithDomain:@"压缩失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"压缩失败,请重新获取"}];
  965 + !failure ? : failure(nil,returnError);
  966 + return;
  967 + }
  968 +
  969 + NSLog(@"Info:\n%@",info);
  970 + AVURLAsset *videoAsset = (AVURLAsset*)avasset;
  971 + // NSLog(@"AVAsset URL: %@",myAsset.URL);
  972 + [strongSelf startExportVideoWithVideoAsset:videoAsset presetName:AVAssetExportPresetMediumQuality outputPath:outputPath success:^(NSString *outputPath) {
  973 + /// 不限制大小
  974 + [strongSelf qnUploadVideoWithToken:token file:outputPath progress:progress success:success failure:failure];
  975 +
  976 + } failure:^(NSString *errorMessage, NSError *error) {
  977 + NSError *returnError = [NSError errorWithDomain:@"压缩失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"压缩失败,请重新获取"}];
  978 + !failure ? : failure(nil,returnError);
  979 + return;
  980 + }];
  981 + }];
  982 +
  983 +
  984 +}
  985 +
  986 +
  987 +///单个视频上传 - 压缩(七牛转码) - 限制 - 筛选) 实现
  988 +- (void)uploadRequestPLShortVideoLimitWithToken:(NSString*)token asset:(id)asset outputPath:(NSString *)outputPath limitType:(AppPhototLimitType)limitType transcode:(transcodeHandlerBlock) transcode progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  989 +
  990 + //七牛token
  991 + if ([NSString isEmpty:token]) {
  992 + dispatch_async(dispatch_get_main_queue(), ^{
  993 + NSError *error = [NSError errorWithDomain:@"七牛token为空" code:100 userInfo:@{NSLocalizedDescriptionKey:@"七牛token为空,请重新获取"}];
  994 + !failure ? : failure(nil,error);
  995 + return;
  996 + });
  997 + }
  998 +
  999 + //上传路径
  1000 + if (!asset) {
  1001 + dispatch_async(dispatch_get_main_queue(), ^{
  1002 + NSError *error = [NSError errorWithDomain:@"上传路径为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"上传为空,请重新获取"}];
  1003 + !failure ? : failure(nil,error);
  1004 + return;
  1005 + });
  1006 +
  1007 + }
  1008 +
  1009 +
  1010 + __weak typeof(self) weakSelf = self;
  1011 +
  1012 + [CNLiveUploadManager zipVideoWithAsset:asset outputPath:outputPath limitType:limitType progressCount:^(float progress) {
  1013 + // 更新压缩进度的 UI
  1014 + NSLog(@"transCoding progress: %f", progress);
  1015 + BOOL isSucess = progress >= 1.0 ? YES : NO;
  1016 + !transcode ? : transcode(progress,isSucess);
  1017 +
  1018 +
  1019 + } success:^(NSURL *url) {
  1020 + __strong typeof(weakSelf) strongSelf = weakSelf;
  1021 + AVAsset *avAsset = [AVAsset assetWithURL:url];
  1022 + NSLog(@"转码后时长%f",[[NSNumber numberWithFloat:CMTimeGetSeconds(avAsset.duration)] floatValue]);
  1023 + NSLog(@"转码后数据大小%ldmb",[NSData dataWithContentsOfURL:url].length / (1024*1024));
  1024 + //不限制大小
  1025 + [strongSelf qnUploadVideoWithToken:token file:url.path progress:progress success:success failure:failure];
  1026 + } failure:^{
  1027 +
  1028 + dispatch_async(dispatch_get_main_queue(), ^{
  1029 + NSError *returnError = [NSError errorWithDomain:@"压缩失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"压缩失败,请重新获取"}];
  1030 + !failure ? : failure(nil,returnError);
  1031 + return;
  1032 +
  1033 + });
  1034 +
  1035 + }];
  1036 +
  1037 +}
  1038 +
  1039 +
  1040 +
  1041 +#pragma mark - AFNetWorking
  1042 +/// (单张image - Image - 压缩或原图 - 限制 - 筛选) 实现
  1043 +- (void)afUploadLimitWithDic:(NSDictionary *)dic url:(NSString *)url type:(CNLiveUploadType)type image:(UIImage *)image isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  1044 +
  1045 + if (!image) {
  1046 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  1047 + !failure ? : failure(nil,error);
  1048 + return;
  1049 + }
  1050 +
  1051 + NSURL *returnUrl = [NSURL URLWithString:url];
  1052 + if (returnUrl.host.length <= 0) {
  1053 +
  1054 + NSError *returnError = [NSError errorWithDomain:@"域名错误" code:400 userInfo:@{NSLocalizedDescriptionKey:@"域名错误"}];
  1055 + !failure ? : failure(nil,returnError);
  1056 + return;
  1057 + }
  1058 +
  1059 + if (type == CNLiveUploadTypeThird) {
  1060 + [CNLiveNetworking setAllowRequestDefaultArgument:NO];
  1061 + }
  1062 +
  1063 + [CNLiveNetworking uploadNetworkWithURLString:url Param:dic FormDataBlock:^(id<AFMultipartFormData> formData) {
  1064 +
  1065 + /*
  1066 + *该方法的参数
  1067 + 1. appendPartWithFileData:要上传的照片[二进制流]
  1068 + 2. name:对应网站上[upload.php中]处理文件的字段(比如upload)
  1069 + 3. fileName:要保存在服务器上的文件名
  1070 + 4. mimeType:上传的文件的类型
  1071 + */
  1072 + NSData *imageData = nil;
  1073 + NSDate *date = [NSDate date];
  1074 + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  1075 + [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
  1076 + NSString *strDate = [dateFormatter stringFromDate:date];
  1077 + int randCount = rand();
  1078 + NSString *fileName = [NSString stringWithFormat:@"Image%d_%@_%d",1,strDate,randCount];
  1079 + NSString *name = @"";
  1080 + if (type == CNLiveUploadTypeThird) {
  1081 + name = @"file";//file
  1082 + }else {
  1083 + name = [NSString stringWithFormat:@"Image%d",1];
  1084 + }
  1085 +
  1086 + NSString *mineType = @"image/jpeg";
  1087 + if (isOriginal) {
  1088 +
  1089 + if (UIImageJPEGRepresentation(image, 1.0)) {
  1090 + imageData = UIImageJPEGRepresentation(image, 1.0);
  1091 + }else {
  1092 + imageData = UIImagePNGRepresentation(image);
  1093 + }
  1094 +
  1095 + }else{
  1096 + imageData = [UIImage zipNSDataWithImage:image];//非原图压缩;
  1097 + }
  1098 +
  1099 + if (!imageData) {
  1100 + NSError *returnError = [NSError errorWithDomain:@"压缩失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"压缩失败,请重新获取"}];
  1101 + !failure ? : failure(nil,returnError);
  1102 + return;
  1103 + }
  1104 + // 筛选
  1105 + if ( [self isImageLimitType:limitType data:imageData]) {
  1106 +
  1107 + }else{
  1108 + NSError *error = [NSError errorWithDomain:@"数据过大" code:104 userInfo:@{NSLocalizedDescriptionKey:@"数据过大,请重新获取"}];
  1109 + !failure ? : failure(nil,error);
  1110 + return;
  1111 +
  1112 + }
  1113 +
  1114 + [formData appendPartWithFileData:imageData name:name fileName:fileName mimeType:mineType];
  1115 +
  1116 + } ProgressBlock:^(NSProgress *uploadProgress) {
  1117 + !progress ? : progress(uploadProgress.fractionCompleted);
  1118 +
  1119 + } CompletionBlock:^(NSURLSessionTask *requestTask, id responseObject, NSError *error) {
  1120 + if (!error) {
  1121 + //成功
  1122 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  1123 + uploadModel.responseObject = responseObject;
  1124 + uploadModel.code = @"200";
  1125 + uploadModel.index = 1;
  1126 + uploadModel.imageUrl = @"";
  1127 + uploadModel.message = @"上传成功";
  1128 +
  1129 + !success ? : success(uploadModel);
  1130 +
  1131 + }else {
  1132 + // 失败
  1133 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  1134 + uploadModel.responseObject = responseObject;
  1135 + uploadModel.code = @"400";
  1136 + uploadModel.index = 1;
  1137 + uploadModel.imageUrl = @"";
  1138 + uploadModel.message = @"上传失败";
  1139 + !failure ? : failure(uploadModel,error);
  1140 + }
  1141 +
  1142 + }];
  1143 +}
  1144 +
  1145 +/// (单张Asset - Image - 压缩或原图 - 限制 - 筛选) 实现
  1146 +- (void)afUploadLimitWithDic:(NSDictionary *)dic url:(NSString *)url type:(CNLiveUploadType)type asset:(id)asset isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  1147 +
  1148 + if (!asset) {
  1149 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  1150 + !failure ? : failure(nil,error);
  1151 + return;
  1152 + }
  1153 +
  1154 + NSURL *returnUrl = [NSURL URLWithString:url];
  1155 + if (returnUrl.host.length <= 0) {
  1156 +
  1157 + NSError *returnError = [NSError errorWithDomain:@"域名错误" code:400 userInfo:@{NSLocalizedDescriptionKey:@"域名错误"}];
  1158 + !failure ? : failure(nil,returnError);
  1159 + return;
  1160 + }
  1161 +
  1162 + if (type == CNLiveUploadTypeThird) {
  1163 + [CNLiveNetworking setAllowRequestDefaultArgument:NO];
  1164 + }
  1165 +
  1166 + [CNLiveNetworking uploadNetworkWithURLString:url Param:dic FormDataBlock:^(id<AFMultipartFormData> formData) {
  1167 +
  1168 +
  1169 + /*
  1170 + *该方法的参数
  1171 + 1. appendPartWithFileData:要上传的照片[二进制流]
  1172 + 2. name:对应网站上[upload.php中]处理文件的字段(比如upload)
  1173 + 3. fileName:要保存在服务器上的文件名
  1174 + 4. mimeType:上传的文件的类型
  1175 + */
  1176 + __block NSData *imageData = nil;
  1177 + NSString *fileName = [NSString stringWithFormat:@"Image%d",1];
  1178 + NSString *name = @"";
  1179 + if (type == CNLiveUploadTypeThird) {
  1180 + name = [NSString stringWithFormat:@"file%d",1];//file
  1181 + }else {
  1182 + name = [NSString stringWithFormat:@"Image%d",1];
  1183 + }
  1184 + NSString *mineType = @"image/jpeg";
  1185 + if ([self getAssetType:asset] == CNAssetModelMediaTypePhotoGif) {
  1186 + mineType = @"image/gif";
  1187 + }
  1188 +
  1189 + //压缩asset
  1190 + [self zipAsset:asset isOriginal:isOriginal success:^(NSData *data) {
  1191 + imageData = data;
  1192 + if (!imageData) {
  1193 + NSError *returnError = [NSError errorWithDomain:@"压缩失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"压缩失败,请重新获取"}];
  1194 + !failure ? : failure(nil,returnError);
  1195 + return;
  1196 + }
  1197 +
  1198 + // 筛选
  1199 + if ( [self isImageLimitType:limitType data:imageData]) {
  1200 +
  1201 + }else{
  1202 + NSError *error = [NSError errorWithDomain:@"数据过大" code:104 userInfo:@{NSLocalizedDescriptionKey:@"数据过大,请重新获取"}];
  1203 + !failure ? : failure(nil,error);
  1204 + return;
  1205 +
  1206 + }
  1207 +
  1208 + [formData appendPartWithFileData:imageData name:name fileName:fileName mimeType:mineType];
  1209 +
  1210 + } failure:^{
  1211 +
  1212 + NSError *returnError = [NSError errorWithDomain:@"压缩失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"压缩失败,请重新获取"}];
  1213 + !failure ? : failure(nil,returnError);
  1214 +
  1215 + }];
  1216 +
  1217 +
  1218 + } ProgressBlock:^(NSProgress *uploadProgress) {
  1219 +
  1220 + !progress ? : progress(uploadProgress.fractionCompleted);
  1221 +
  1222 + } CompletionBlock:^(NSURLSessionTask *requestTask, id responseObject, NSError *error) {
  1223 +
  1224 + if (!error) {
  1225 + //成功
  1226 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  1227 + uploadModel.responseObject = responseObject;
  1228 + uploadModel.code = @"200";
  1229 + uploadModel.index = 1;
  1230 + uploadModel.imageUrl = @"";
  1231 + uploadModel.message = @"上传成功";
  1232 +
  1233 + !success ? : success(uploadModel);
  1234 +
  1235 + }else{
  1236 + //失败
  1237 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  1238 + uploadModel.responseObject = responseObject;
  1239 + uploadModel.code = @"400";
  1240 + uploadModel.index = 1;
  1241 + uploadModel.imageUrl = @"";
  1242 + uploadModel.message = @"上传失败";
  1243 +
  1244 + !failure ? : failure(uploadModel,error);
  1245 +
  1246 + }
  1247 +
  1248 + }];
  1249 +
  1250 +}
  1251 +
  1252 +/// (多张Image - ImageArray - 压缩或原图 - 限制 - 筛选) 实现
  1253 +- (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 {
  1254 +
  1255 + if (imageArray.count <= 0 ) {
  1256 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  1257 + !failure ? : failure(nil,error);
  1258 + return;
  1259 + }
  1260 +
  1261 + NSURL *returnUrl = [NSURL URLWithString:url];
  1262 + if (returnUrl.host.length <= 0) {
  1263 +
  1264 + NSError *returnError = [NSError errorWithDomain:@"域名错误" code:400 userInfo:@{NSLocalizedDescriptionKey:@"域名错误"}];
  1265 + !failure ? : failure(nil,returnError);
  1266 + return;
  1267 + }
  1268 +
  1269 + [CNLiveNetworking uploadNetworkWithURLString:url Param:dic FormDataBlock:^(id<AFMultipartFormData> formData) {
  1270 + //配置参数
  1271 + [imageArray enumerateObjectsUsingBlock:^(UIImage * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  1272 +
  1273 + /*
  1274 + *该方法的参数
  1275 + 1. appendPartWithFileData:要上传的照片[二进制流]
  1276 + 2. name:对应网站上[upload.php中]处理文件的字段(比如upload)
  1277 + 3. fileName:要保存在服务器上的文件名
  1278 + 4. mimeType:上传的文件的类型
  1279 + */
  1280 + UIImage *image = imageArray[idx];
  1281 + if (!image) {
  1282 + return;
  1283 + }
  1284 + NSData *imageData = nil;
  1285 + NSString *fileName = [NSString stringWithFormat:@"Image%ld",idx +1];
  1286 + NSString *name = [NSString stringWithFormat:@"Image%ld",idx +1];
  1287 + NSString *mineType = @"image/jpeg";
  1288 + if (isOriginal) {
  1289 +
  1290 + if (UIImageJPEGRepresentation(image, 1.0)) {
  1291 + imageData = UIImageJPEGRepresentation(image, 1.0);
  1292 + }else {
  1293 + imageData = UIImagePNGRepresentation(image);
  1294 + }
  1295 +
  1296 + }else{
  1297 + imageData = [UIImage zipNSDataWithImage:image];//非原图压缩;
  1298 + }
  1299 +
  1300 + if (!imageData) {
  1301 + return;
  1302 + }
  1303 + // 筛选
  1304 + if ( [self isImageLimitType:limitType data:imageData]) {
  1305 +
  1306 + }else{
  1307 + return;
  1308 +
  1309 + }
  1310 +
  1311 + [formData appendPartWithFileData:imageData name:name fileName:fileName mimeType:mineType];
  1312 +
  1313 + }];
  1314 +
  1315 + } ProgressBlock:^(NSProgress *uploadProgress) {
  1316 + !progress ? : progress(uploadProgress.fractionCompleted);
  1317 + } CompletionBlock:^(NSURLSessionTask *requestTask, id responseObject, NSError *error) {
  1318 +
  1319 + NSMutableArray *fileArray = [NSMutableArray array];
  1320 + if (!error) {
  1321 + //成功
  1322 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  1323 + uploadModel.responseObject = responseObject;
  1324 + uploadModel.code = @"200";
  1325 + uploadModel.index = 1;
  1326 + uploadModel.imageUrl = @"";
  1327 + uploadModel.message = @"上传成功";
  1328 + [fileArray addObject:uploadModel];
  1329 + !success ? : success(fileArray);
  1330 +
  1331 + }else
  1332 + {
  1333 + //失败
  1334 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  1335 + uploadModel.responseObject = responseObject;
  1336 + uploadModel.code = @"400";
  1337 + uploadModel.index = 1;
  1338 + uploadModel.imageUrl = @"";
  1339 + uploadModel.message = @"上传失败";
  1340 + [fileArray addObject:uploadModel];
  1341 + !success ? : success(fileArray);
  1342 +
  1343 + }
  1344 +
  1345 + }];
  1346 +
  1347 +
  1348 +}
  1349 +
  1350 +/// (多张Asset - AssetArray - 压缩或原图 - 限制 - 筛选) 实现
  1351 +- (void)afUploadLimitWithDic:(NSDictionary *)dic url:(NSString *)url type:(CNLiveUploadType)type assetArray:(NSMutableArray *)assetArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  1352 +
  1353 + if (assetArray.count <= 0 ) {
  1354 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  1355 + !failure ? : failure(nil,error);
  1356 + return;
  1357 + }
  1358 +
  1359 + NSURL *returnUrl = [NSURL URLWithString:url];
  1360 + if (returnUrl.host.length <= 0) {
  1361 +
  1362 + NSError *returnError = [NSError errorWithDomain:@"域名错误" code:400 userInfo:@{NSLocalizedDescriptionKey:@"域名错误"}];
  1363 + !failure ? : failure(nil,returnError);
  1364 + return;
  1365 + }
  1366 +
  1367 +
  1368 +
  1369 + [CNLiveNetworking uploadNetworkWithURLString:url Param:dic FormDataBlock:^(id<AFMultipartFormData> formData) {
  1370 +
  1371 + [assetArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  1372 +
  1373 + /*
  1374 + *该方法的参数
  1375 + 1. appendPartWithFileData:要上传的照片[二进制流]
  1376 + 2. name:对应网站上[upload.php中]处理文件的字段(比如upload)
  1377 + 3. fileName:要保存在服务器上的文件名
  1378 + 4. mimeType:上传的文件的类型
  1379 + */
  1380 + id asset = assetArray[idx];
  1381 + if (!asset) {
  1382 + return;
  1383 + }
  1384 + __block NSData *imageData = nil;
  1385 + NSString *fileName = [NSString stringWithFormat:@"Image%ld",idx+1];
  1386 + NSString *name = [NSString stringWithFormat:@"Image%ld",idx+1];
  1387 + NSString *mineType = @"image/jpeg";
  1388 + if ([self getAssetType:asset] == CNAssetModelMediaTypePhotoGif) {
  1389 + mineType = @"image/gif";
  1390 + }
  1391 +
  1392 + //压缩asset
  1393 + [self zipAsset:asset isOriginal:isOriginal success:^(NSData *data) {
  1394 + imageData = data;
  1395 + if (!imageData) {
  1396 + NSError *returnError = [NSError errorWithDomain:@"压缩失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"压缩失败,请重新获取"}];
  1397 + !failure ? : failure(nil,returnError);
  1398 + return;
  1399 + }
  1400 +
  1401 + // 筛选
  1402 + if ( [self isImageLimitType:limitType data:imageData]) {
  1403 +
  1404 + }else{
  1405 + NSError *error = [NSError errorWithDomain:@"数据过大" code:104 userInfo:@{NSLocalizedDescriptionKey:@"数据过大,请重新获取"}];
  1406 + !failure ? : failure(nil,error);
  1407 + return;
  1408 +
  1409 + }
  1410 +
  1411 + [formData appendPartWithFileData:imageData name:name fileName:fileName mimeType:mineType];
  1412 +
  1413 + } failure:^{
  1414 + NSError *returnError = [NSError errorWithDomain:@"压缩失败" code:105 userInfo:@{NSLocalizedDescriptionKey:@"压缩失败,请重新获取"}];
  1415 + !failure ? : failure(nil,returnError);
  1416 + return;
  1417 +
  1418 + }];
  1419 +
  1420 + }];
  1421 +
  1422 + } ProgressBlock:^(NSProgress *uploadProgress) {
  1423 +
  1424 + !progress ? : progress(uploadProgress.fractionCompleted);
  1425 +
  1426 +
  1427 + } CompletionBlock:^(NSURLSessionTask *requestTask, id responseObject, NSError *error) {
  1428 +
  1429 + NSMutableArray *array = [NSMutableArray array];
  1430 + if (!error) {
  1431 + //成功
  1432 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  1433 + uploadModel.responseObject = responseObject;
  1434 + uploadModel.code = @"200";
  1435 + uploadModel.index = 1;
  1436 + uploadModel.imageUrl = @"";
  1437 + uploadModel.message = @"上传成功";
  1438 + [array addObject:uploadModel];
  1439 + !success ? : success(array);
  1440 +
  1441 + }else
  1442 + {
  1443 + //失败
  1444 + CNLiveUploadModel *uploadModel = [[CNLiveUploadModel alloc]init];
  1445 + uploadModel.responseObject = responseObject;
  1446 + uploadModel.code = @"400";
  1447 + uploadModel.index = 1;
  1448 + uploadModel.imageUrl = @"";
  1449 + uploadModel.message = @"上传失败";
  1450 + [array addObject:uploadModel];
  1451 + !success ? : success(array);
  1452 +
  1453 + }
  1454 +
  1455 + }];
  1456 +
  1457 +}
  1458 +
  1459 +
  1460 +#pragma mark - 业务层_1
  1461 +/// 单张上传NSData
  1462 ++ (void)uploadType:(CNLiveUploadType)type token:(NSString*)token data:(NSData *)data progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  1463 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1464 + [[CNLiveUploadManager shareInsance]qnUploadWithToken:token data:data progress:progress success:success failure:failure];
  1465 + }else if (type == CNLiveUploadTypeKS) {
  1466 +
  1467 + }else{
  1468 +
  1469 + }
  1470 +}
  1471 +
  1472 +///单张上传UIImage
  1473 ++ (void)uploadType:(CNLiveUploadType)type token:(NSString*)token image:(UIImage *)image progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  1474 +
  1475 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1476 + [[CNLiveUploadManager shareInsance]qnUploadWithToken:token image:image progress:progress success:success failure:failure];
  1477 + }else if (type == CNLiveUploadTypeKS) {
  1478 +
  1479 + }else{
  1480 +
  1481 + }
  1482 +}
  1483 +
  1484 +/// CNLive上传多张NSData
  1485 ++ (void)uploadType:(CNLiveUploadType)type token:(NSString*)token dataArray:(NSMutableArray<NSData *> *)dataArray progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  1486 +
  1487 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1488 + [[CNLiveUploadManager shareInsance]qnUploadWithToken:token dataArray:dataArray progress:progress success:success failure:failure];
  1489 + }else if (type == CNLiveUploadTypeKS) {
  1490 +
  1491 + }else{
  1492 +
  1493 + }
  1494 +
  1495 +}
  1496 +
  1497 +/// (视频)路径上传
  1498 ++ (void)uploadVideoType:(CNLiveUploadType)type file:(NSString *)file token:(NSString *)token progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  1499 +
  1500 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1501 + [[CNLiveUploadManager shareInsance]qnUploadVideoWithToken:token file:file progress:progress success:success failure:failure];
  1502 + }else if (type == CNLiveUploadTypeKS) {
  1503 +
  1504 + }else{
  1505 +
  1506 + }
  1507 +
  1508 +}
  1509 +
  1510 +#pragma mark - 业务部分
  1511 +
  1512 +/// 单图上传 (asset取得Image - 压缩或原图 - 限制 - 筛选)
  1513 ++ (void)uploadLimitType:(CNLiveUploadType)type phAsset:(PHAsset *)phAsset isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType token:(NSString *)token progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  1514 +
  1515 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1516 +
  1517 + if ([PHAsset isKindOfClass:[PHAsset class]]) {
  1518 +
  1519 + [[CNLiveUploadManager shareInsance]qnUploadLimitWithToken:token phAsset:phAsset isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1520 +
  1521 + }else {
  1522 + NSError *error = [NSError errorWithDomain:@"图片错误" code:101 userInfo:@{NSLocalizedDescriptionKey:@"上传为空,请重新获取"}];
  1523 + !failure ? : failure(nil,error);
  1524 + return;
  1525 + }
  1526 +
  1527 + }else if (type == CNLiveUploadTypeKS) {
  1528 +
  1529 + }else{
  1530 +
  1531 + }
  1532 +}
  1533 +
  1534 +
  1535 +/// 单图上传 (Image - 压缩或原图 - 限制 - 筛选)
  1536 ++ (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 {
  1537 +
  1538 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1539 +
  1540 + [[CNLiveUploadManager shareInsance]qnUploadLimitWithToken:token image:image isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1541 +
  1542 + }else if (type == CNLiveUploadTypeKS) {
  1543 +
  1544 + }else{
  1545 +
  1546 + }
  1547 +
  1548 +}
  1549 +
  1550 +/// 多张图上传 (images - 压缩或原图 - 限制 - 筛选)
  1551 ++ (void)uploadLimitType:(CNLiveUploadType)type imageArray:(NSMutableArray *)imageArray assetArray:(NSMutableArray *)assetArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType token:(NSString *)token progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  1552 +
  1553 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1554 + [[CNLiveUploadManager shareInsance] qnUploadLimitWithToken:token imageArray:imageArray assetArray:assetArray isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1555 +
  1556 + }else if (type == CNLiveUploadTypeKS) {
  1557 +
  1558 + }else{
  1559 +
  1560 + }
  1561 +
  1562 +}
  1563 +
  1564 +/// 多张图上传 (assetArray - 压缩 - 限制 - 筛选)
  1565 ++ (void)uploadLimitType:(CNLiveUploadType)type token:(NSString *)token phAssetArray:(NSMutableArray<PHAsset *> *)phAssetArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  1566 +
  1567 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1568 + [[CNLiveUploadManager shareInsance] qnUploadLimitWithToken:token phAssetArray:phAssetArray isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1569 +
  1570 + }else if (type == CNLiveUploadTypeKS) {
  1571 +
  1572 + }else{
  1573 +
  1574 + }
  1575 +
  1576 +}
  1577 +
  1578 +
  1579 +/// 单个视频系统视频上传 (video - 压缩 - 限制 - 筛选)
  1580 ++ (void)uploadLimitVideoType:(CNLiveUploadType)type token:(NSString *)token asset:(id)asset limitType:(AppPhototLimitType)limitType outputPath:(NSString *)outputPath progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  1581 +
  1582 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1583 + [[CNLiveUploadManager shareInsance] qnUploadVideoLimitWithToken:token asset:asset limitType:limitType outputPath:(NSString *)outputPath progress:progress success:success failure:failure];
  1584 +
  1585 + }else if (type == CNLiveUploadTypeKS) {
  1586 +
  1587 + }else{
  1588 +
  1589 + }
  1590 +
  1591 +}
  1592 +
  1593 +#pragma mark - 业务_请求token + 上传
  1594 +/// 请求token 单张上传 (asset - 压缩 - 限制 - 筛选)
  1595 ++ (void)uploadRequestType:(CNLiveUploadType)type url:(NSString *)url dic:(NSDictionary *)dic phAsset:(id)phAsset isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure{
  1596 +
  1597 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1598 + [[HttpService service] sendRequestWithHttpMethod:E_HTTP_REQUEST_METHOD_POST URLPath:url parameters:dic isCache:NO CheckParam:nil completionHandler:^(id data, NSError *error) {
  1599 +
  1600 + NSDictionary *dic = (NSDictionary *)data;
  1601 + if (!error && [dic containsObjectForKey:@"token"]) {
  1602 + NSString *token = dic[@"token"];
  1603 + if ([phAsset isKindOfClass:[PHAsset class]]) {
  1604 +
  1605 + [[CNLiveUploadManager shareInsance]qnUploadLimitWithToken:token phAsset:(PHAsset *)phAsset isOriginal:(BOOL) isOriginal limitType:limitType progress:progress success:success failure:failure];
  1606 +
  1607 + }else {
  1608 + NSError *error = [NSError errorWithDomain:@"数据为空" code:101 userInfo:@{NSLocalizedDescriptionKey:@"数据为空,请重新获取"}];
  1609 + !failure ? : failure(nil,error);
  1610 + return;
  1611 + }
  1612 +
  1613 + } else {//请求token失败
  1614 +
  1615 + NSError *error = [NSError errorWithDomain:@"请求token失败" code:100 userInfo:@{NSLocalizedDescriptionKey:@"请求token失败,请重新获取"}];
  1616 + !failure ? : failure(nil,error);
  1617 + return;
  1618 + }
  1619 +
  1620 + }];
  1621 +
  1622 +
  1623 + }else if (type == CNLiveUploadTypeKS) {
  1624 +
  1625 + }else{
  1626 + //单张上传
  1627 + [[CNLiveUploadManager shareInsance]afUploadLimitWithDic:dic url:url type:type asset:phAsset isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1628 +
  1629 + }
  1630 +
  1631 +}
  1632 +
  1633 +/// 请求token 单图上传 (Image - 压缩或原图 - 限制 - 筛选)
  1634 ++ (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 {
  1635 +
  1636 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1637 + [[HttpService service] sendRequestWithHttpMethod:E_HTTP_REQUEST_METHOD_POST URLPath:url parameters:dic isCache:NO CheckParam:nil completionHandler:^(id data, NSError *error) {
  1638 +
  1639 + NSDictionary *dic = (NSDictionary *)data;
  1640 + if (!error && [dic containsObjectForKey:@"token"]) {
  1641 + NSString *token = dic[@"token"];
  1642 + [[CNLiveUploadManager shareInsance]qnUploadLimitWithToken:token image:image isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1643 +
  1644 + } else {//请求token失败
  1645 +
  1646 + NSError *error = [NSError errorWithDomain:@"请求token失败" code:100 userInfo:@{NSLocalizedDescriptionKey:@"请求token失败,请重新获取"}];
  1647 + !failure ? : failure(nil,error);
  1648 + return;
  1649 + }
  1650 +
  1651 + }];
  1652 +
  1653 +
  1654 + }else if (type == CNLiveUploadTypeKS) {
  1655 +
  1656 + }else{
  1657 + //单张上传
  1658 + [[CNLiveUploadManager shareInsance]afUploadLimitWithDic:dic url:url type:type image:image isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1659 +
  1660 + }
  1661 +
  1662 +}
  1663 +
  1664 +/// 请求token 多张图上传 (images - 压缩或原图 - 限制 - 筛选)
  1665 ++ (void)uploadRequestType:(CNLiveUploadType)type url:(NSString *)url dic:(NSDictionary *)dic imageArray:(NSMutableArray *)imageArray assetArray:(NSMutableArray *)assetArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  1666 +
  1667 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1668 + [[HttpService service] sendRequestWithHttpMethod:E_HTTP_REQUEST_METHOD_POST URLPath:url parameters:dic isCache:NO CheckParam:nil completionHandler:^(id data, NSError *error) {
  1669 +
  1670 + NSDictionary *dic = (NSDictionary *)data;
  1671 + if (!error && [dic containsObjectForKey:@"token"]) {
  1672 + NSString *token = dic[@"token"];
  1673 + [[CNLiveUploadManager shareInsance] qnUploadLimitWithToken:token imageArray:imageArray assetArray:assetArray isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1674 +
  1675 + } else {//请求token失败
  1676 +
  1677 +
  1678 + !failure ? : failure(nil,error);
  1679 + return;
  1680 + }
  1681 +
  1682 + }];
  1683 +
  1684 +
  1685 + }else if (type == CNLiveUploadTypeKS) {
  1686 +
  1687 + }else{
  1688 + [[CNLiveUploadManager shareInsance]afUploadLimitWithDic:dic url:url imageArray:imageArray isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1689 +
  1690 + }
  1691 +
  1692 +}
  1693 +
  1694 +/// 请求token (assetArray - 压缩 - 限制 - 筛选)
  1695 ++ (void)uploadRequestType:(CNLiveUploadType)type url:(NSString *)url dic:(NSDictionary *)dic phAssetArray:(NSMutableArray<PHAsset *> *)phAssetArray isOriginal:(BOOL) isOriginal limitType:(AppPhototLimitType)limitType progress:(progressHandlerBlock)progress success:(successBlock)success failure:(failureBlock)failure {
  1696 +
  1697 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1698 + [[HttpService service] sendRequestWithHttpMethod:E_HTTP_REQUEST_METHOD_POST URLPath:url parameters:dic isCache:NO CheckParam:nil completionHandler:^(id data, NSError *error) {
  1699 +
  1700 + NSDictionary *dic = (NSDictionary *)data;
  1701 + if (!error && [dic containsObjectForKey:@"token"]) {
  1702 + NSString *token = dic[@"token"];
  1703 + [[CNLiveUploadManager shareInsance] qnUploadLimitWithToken:token phAssetArray:phAssetArray isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1704 +
  1705 + } else {//请求token失败
  1706 +
  1707 + NSError *error = [NSError errorWithDomain:@"请求token失败" code:100 userInfo:@{NSLocalizedDescriptionKey:@"请求token失败,请重新获取"}];
  1708 + !failure ? : failure(nil,error);
  1709 + return;
  1710 + }
  1711 +
  1712 + }];
  1713 +
  1714 +
  1715 + }else if (type == CNLiveUploadTypeKS) {
  1716 +
  1717 + }else{
  1718 + //多张上传
  1719 + [[CNLiveUploadManager shareInsance] afUploadLimitWithDic:dic url:url type:type assetArray:phAssetArray isOriginal:isOriginal limitType:limitType progress:progress success:success failure:failure];
  1720 +
  1721 + }
  1722 +
  1723 +}
  1724 +
  1725 +/// 请求token 单个视频上传 (video - 压缩 - 限制 - 筛选)
  1726 ++ (void)uploadRequestVideoType:(CNLiveUploadType)type url:(NSString *)url dic:(NSDictionary *)dic asset:(id)asset limitType:(AppPhototLimitType)limitType outputPath:(NSString *)outputPath progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  1727 +
  1728 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1729 + [[HttpService service] sendRequestWithHttpMethod:E_HTTP_REQUEST_METHOD_POST URLPath:url parameters:dic isCache:NO CheckParam:nil completionHandler:^(id data, NSError *error) {
  1730 +
  1731 + NSDictionary *dic = (NSDictionary *)data;
  1732 + if (!error && [dic containsObjectForKey:@"token"]) {
  1733 + NSString *token = dic[@"token"];
  1734 + [[CNLiveUploadManager shareInsance] qnUploadVideoLimitWithToken:token asset:asset limitType:limitType outputPath:outputPath progress:progress success:success failure:failure];
  1735 +
  1736 + } else {//请求token失败
  1737 +
  1738 + NSError *error = [NSError errorWithDomain:@"请求token失败" code:100 userInfo:@{NSLocalizedDescriptionKey:@"请求token失败,请重新获取"}];
  1739 + !failure ? : failure(nil,error);
  1740 + return;
  1741 + }
  1742 +
  1743 + }];
  1744 +
  1745 +
  1746 + }else if (type == CNLiveUploadTypeKS) {
  1747 +
  1748 + }else{
  1749 +
  1750 + }
  1751 +
  1752 +}
  1753 +
  1754 +/// 请求token 单个视频上传 (video - 七牛短视频压缩 - 限制 - 筛选)
  1755 ++ (void)uploadRequestWhithPLShortVideoType:(CNLiveUploadType)type outputPath:(NSString *)outputPath url:(NSString *)url dic:(NSDictionary *)dic asset:(id)asset limitType:(AppPhototLimitType)limitType transcode:(transcodeHandlerBlock) transcode progress:(progressHandlerBlock)progress success:(successModelBlock)success failure:(failureModelBlock)failure {
  1756 +
  1757 + if (type == CNLiveUploadTypeQN) { //七牛上传
  1758 + [[HttpService service] sendRequestWithHttpMethod:E_HTTP_REQUEST_METHOD_POST URLPath:url parameters:dic isCache:NO CheckParam:nil completionHandler:^(id data, NSError *error) {
  1759 +
  1760 + NSDictionary *dic = (NSDictionary *)data;
  1761 + if (!error && [dic containsObjectForKey:@"token"]) {
  1762 + NSString *token = dic[@"token"];
  1763 + [[CNLiveUploadManager shareInsance] uploadRequestPLShortVideoLimitWithToken:token asset:asset outputPath:outputPath limitType:limitType transcode: transcode progress:progress success:success failure:failure];
  1764 +
  1765 + } else {//请求token失败
  1766 + dispatch_async(dispatch_get_main_queue(), ^{
  1767 +// NSError *error = [NSError errorWithDomain:@"请求token失败" code:100 userInfo:@{NSLocalizedDescriptionKey:@"请求token失败,请重新获取"}];
  1768 + !failure ? : failure(nil,error);
  1769 + return;
  1770 + });
  1771 + }
  1772 +
  1773 + }];
  1774 +
  1775 + }else if (type == CNLiveUploadTypeKS) {
  1776 +
  1777 + }else{
  1778 +
  1779 + }
  1780 +
  1781 +}
  1782 +
  1783 +
  1784 +#pragma mark - 私有方法
  1785 +///筛选 是否视频在限制内
  1786 +- (BOOL)isVideoLimitType:(AppPhototLimitType)limitType data:(NSData *)data{
  1787 + switch (limitType) {
  1788 + case AppPhototLimitTypeChat://聊天视频
  1789 + if (data.length <= kChat_limit_video) {
  1790 + return YES;
  1791 + }else{
  1792 + return NO;
  1793 + }
  1794 + break;
  1795 + case AppPhototLimitTypeFriendsCircle://朋友圈
  1796 + if (data.length <= kFirendsCircle_limit_video) {
  1797 + return YES;
  1798 + }else{
  1799 + return NO;
  1800 + }
  1801 + break;
  1802 +
  1803 + default:
  1804 + if (data.length <= 20*1024*1024) {
  1805 + return YES;
  1806 + }else{
  1807 + return NO;
  1808 + }
  1809 + break;
  1810 + }
  1811 +}
  1812 +
  1813 +/// 筛选 是否图片在限制内
  1814 +- (BOOL)isImageLimitType:(AppPhototLimitType)limitType data:(NSData *)data {
  1815 +
  1816 + switch (limitType) {
  1817 + case AppPhototLimitTypeChat://聊天
  1818 + if (data.length <= kChat_limit_photo) {
  1819 + return YES;
  1820 + }else{
  1821 + return NO;
  1822 + }
  1823 + break;
  1824 + case AppPhototLimitTypeFriendsCircle://朋友圈
  1825 + if (data.length <= kFriendsCircle_limit_photo) {
  1826 + return YES;
  1827 + }else{
  1828 + return NO;
  1829 + }
  1830 + break;
  1831 + case AppPhototLimitTypeSweepCode://扫码
  1832 + if (data.length <= kSweepCode_limit_phoho) {
  1833 + return YES;
  1834 + }else{
  1835 + return NO;
  1836 + }
  1837 + break;
  1838 + case AppPhototLimitTypeTarentoComment://评论
  1839 + if (data.length <= kTarentoComment_limit_photo) {
  1840 + return YES;
  1841 + }else{
  1842 + return NO;
  1843 + }
  1844 + break;
  1845 +
  1846 + default:
  1847 + if (data.length <= 10*1024*1024) {
  1848 + return YES;
  1849 + }else{
  1850 + return NO;
  1851 + }
  1852 + break;
  1853 + }
  1854 +
  1855 +}
  1856 +
  1857 +#pragma mark - 压缩方法
  1858 +
  1859 +/// 图片压缩
  1860 +- (void )zipAsset:(PHAsset *) asset isOriginal:(BOOL) isOriginal success:(void(^)(NSData * data))success failure:(void(^)(void))failure {
  1861 +
  1862 + if ([asset isKindOfClass:[PHAsset class]]) {
  1863 + __block NSData *data = nil;
  1864 + if ([self getAssetType:asset] == CNAssetModelMediaTypePhotoGif) {
  1865 +
  1866 + PHImageManager *imageManager = [PHImageManager defaultManager];
  1867 + PHImageRequestOptions *options = [PHImageRequestOptions new];
  1868 + options.deliveryMode = PHImageRequestOptionsDeliveryModeFastFormat;
  1869 + options.resizeMode = PHImageRequestOptionsResizeModeFast;
  1870 + options.synchronous = NO;
  1871 + [imageManager requestImageDataForAsset:asset options:options resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
  1872 + if (imageData) {
  1873 + data = imageData;
  1874 + !success ? : success(data);
  1875 + }else {
  1876 + !failure ? : failure();
  1877 + }
  1878 + }];
  1879 +
  1880 + }else {//图片
  1881 +
  1882 + PHImageManager *imageManager = [PHImageManager defaultManager];
  1883 + PHImageRequestOptions *options = [PHImageRequestOptions new];
  1884 + options.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;
  1885 + options.resizeMode = PHImageRequestOptionsResizeModeFast;
  1886 + options.synchronous = NO;
  1887 + [imageManager requestImageDataForAsset:asset options:options resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
  1888 + if (imageData) {
  1889 + UIImage *result = [UIImage imageWithData:imageData];
  1890 + if (result) {
  1891 +
  1892 + if (isOriginal) {
  1893 + if (UIImageJPEGRepresentation(result, 1.0)) {
  1894 + data = UIImageJPEGRepresentation(result, 1.0);
  1895 + }else {
  1896 + data = UIImagePNGRepresentation(result);
  1897 + }
  1898 + }else{
  1899 + data = [UIImage zipNSDataWithImage:result];//压缩
  1900 + }
  1901 + !success ? : success(data);
  1902 +
  1903 + }else{
  1904 + !failure ? : failure();
  1905 + }
  1906 +
  1907 +
  1908 + }else {
  1909 + !failure ? : failure();
  1910 + }
  1911 + }];
  1912 + }
  1913 +
  1914 + }else {
  1915 + !failure ? : failure();
  1916 +
  1917 + }
  1918 +
  1919 +}
  1920 +
  1921 +/// 图片和Asset压缩
  1922 +- (void )zipAsset:(id) phAsset image:(UIImage *)image isOriginal:(BOOL) isOriginal success:(void(^)(NSData * data))success{
  1923 +
  1924 + PHAsset *asset = phAsset;
  1925 + UIImage *origionImg = image;
  1926 + NSData *data = nil;
  1927 + if ([self getAssetType:asset] == CNAssetModelMediaTypePhotoGif) {
  1928 + data = [asset gifData];
  1929 + !success ? : success(data);
  1930 +
  1931 + }else{
  1932 + //压缩
  1933 + if (isOriginal) {
  1934 + if (UIImageJPEGRepresentation(origionImg, 1.0)) {
  1935 + data = UIImageJPEGRepresentation(origionImg, 1.0);
  1936 + }else {
  1937 + data = UIImagePNGRepresentation(origionImg);
  1938 + }
  1939 + }else{
  1940 + data = [UIImage zipNSDataWithImage:origionImg];//压缩
  1941 + }
  1942 + !success ? : success(data);
  1943 +
  1944 + }
  1945 +
  1946 +}
  1947 +
  1948 ++ (NSString *)createVideoFolderOutputPath:(NSString *)outputPath
  1949 +{
  1950 +
  1951 + if (outputPath) {
  1952 + return [CNLiveUploadManager checkFilePath:outputPath];
  1953 + }
  1954 + return [CNLiveUploadManager chatFilePathByName:@"上传"];
  1955 +
  1956 +}
  1957 +
  1958 ++ (nullable NSString *)checkFilePath:(NSString *)path {
  1959 +
  1960 + NSFileManager *fileManager = [NSFileManager defaultManager];
  1961 +
  1962 + BOOL isDir = NO;
  1963 +
  1964 + // fileExistsAtPath 判断一个文件或目录是否有效,isDirectory判断是否一个目录
  1965 + BOOL existed = [fileManager fileExistsAtPath:path isDirectory:&isDir];
  1966 +
  1967 + if ( !(isDir == YES && existed == YES) ) {
  1968 +
  1969 + return [CNLiveUploadManager chatFilePathByName:@"上传"];
  1970 + }
  1971 +
  1972 + return path;
  1973 +
  1974 +}
  1975 +
  1976 +//用户ID
  1977 ++ (nullable NSString *)chatFilePathByName:(NSString *_Nonnull)name{
  1978 +
  1979 + // NSHomeDirectory():应用程序目录, @"tmp/temp":在tmp文件夹下创建temp 文件夹
  1980 + NSString *tempName = [NSString stringWithFormat:@"%@/",name];
  1981 +
  1982 + NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:tempName];
  1983 +
  1984 + NSFileManager *fileManager = [NSFileManager defaultManager];
  1985 +
  1986 + BOOL isDir = NO;
  1987 +
  1988 + // fileExistsAtPath 判断一个文件或目录是否有效,isDirectory判断是否一个目录
  1989 + BOOL existed = [fileManager fileExistsAtPath:filePath isDirectory:&isDir];
  1990 +
  1991 + if ( !(isDir == YES && existed == YES) ) {
  1992 +
  1993 + // 在 temp 目录下创建一临时文件
  1994 + [fileManager createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:nil];
  1995 + }
  1996 +
  1997 + return filePath;
  1998 +}
  1999 +
  2000 +
  2001 +//系统视频导出
  2002 +- (void)startExportVideoWithVideoAsset:(AVURLAsset *)videoAsset presetName:(NSString *)presetName outputPath:(NSString *)outputPath success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure {
  2003 + // Find compatible presets by video asset.
  2004 + NSArray *presets = [AVAssetExportSession exportPresetsCompatibleWithAsset:videoAsset];
  2005 +
  2006 + // Begin to compress video
  2007 + // Now we just compress to low resolution if it supports
  2008 + // If you need to upload to the server, but server does't support to upload by streaming,
  2009 + // You can compress the resolution to lower. Or you can support more higher resolution.
  2010 + if ([presets containsObject:presetName]) {
  2011 + AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:videoAsset presetName:presetName];
  2012 +
  2013 + NSDateFormatter *formater = [[NSDateFormatter alloc] init];
  2014 + [formater setDateFormat:@"yyyy-MM-dd-HH:mm:ss-SSS"];
  2015 + NSString *filaName = [NSString stringWithFormat:@"output-%@_%d_fileType=videoType.mp4",[formater stringFromDate:[NSDate date]],arc4random()];
  2016 + // NSString *outputPath = [NSHomeDirectory() stringByAppendingFormat:@"/tmp/output-%@.mp4", [formater stringFromDate:[NSDate date]]];
  2017 + NSString *editOutputPath = @"";
  2018 + editOutputPath = [CNLiveUploadManager createVideoFolderOutputPath:outputPath];
  2019 +
  2020 + NSLog(@"video outputPath = %@",editOutputPath);
  2021 +
  2022 + session.outputURL = [NSURL fileURLWithPath:editOutputPath];
  2023 +
  2024 + // Optimize for network use.
  2025 + session.shouldOptimizeForNetworkUse = true;
  2026 +
  2027 + NSArray *supportedTypeArray = session.supportedFileTypes;
  2028 + if ([supportedTypeArray containsObject:AVFileTypeMPEG4]) {
  2029 + session.outputFileType = AVFileTypeMPEG4;
  2030 + } else if (supportedTypeArray.count == 0) {
  2031 + if (failure) {
  2032 + failure(@"该视频类型暂不支持导出", nil);
  2033 + }
  2034 + NSLog(@"No supported file types 视频类型暂不支持导出");
  2035 + return;
  2036 + } else {
  2037 + session.outputFileType = [supportedTypeArray objectAtIndex:0];
  2038 + }
  2039 +
  2040 + if (![[NSFileManager defaultManager] fileExistsAtPath:[NSHomeDirectory() stringByAppendingFormat:@"/tmp"]]) {
  2041 + [[NSFileManager defaultManager] createDirectoryAtPath:[NSHomeDirectory() stringByAppendingFormat:@"/tmp"] withIntermediateDirectories:YES attributes:nil error:nil];
  2042 + }
  2043 +
  2044 + // Begin to export video to the output path asynchronously.
  2045 + [session exportAsynchronouslyWithCompletionHandler:^(void) {
  2046 + dispatch_async(dispatch_get_main_queue(), ^{
  2047 +
  2048 + switch (session.status) {
  2049 + case AVAssetExportSessionStatusUnknown: {
  2050 + NSLog(@"AVAssetExportSessionStatusUnknown");
  2051 + if (failure) {
  2052 + failure(@"视频导出失败", session.error);
  2053 + }
  2054 + } break;
  2055 + case AVAssetExportSessionStatusWaiting: {
  2056 + NSLog(@"AVAssetExportSessionStatusWaiting");
  2057 + } break;
  2058 + case AVAssetExportSessionStatusExporting: {
  2059 + NSLog(@"AVAssetExportSessionStatusExporting");
  2060 + } break;
  2061 + case AVAssetExportSessionStatusCompleted: {
  2062 + NSLog(@"AVAssetExportSessionStatusCompleted");
  2063 + if (success) {
  2064 + success(outputPath);
  2065 + }
  2066 + } break;
  2067 + case AVAssetExportSessionStatusFailed: {
  2068 + NSLog(@"AVAssetExportSessionStatusFailed");
  2069 + if (failure) {
  2070 + failure(@"视频导出失败", session.error);
  2071 + }
  2072 + } break;
  2073 + case AVAssetExportSessionStatusCancelled: {
  2074 + NSLog(@"AVAssetExportSessionStatusCancelled");
  2075 + if (failure) {
  2076 + failure(@"导出任务已被取消", nil);
  2077 + }
  2078 + } break;
  2079 + default:
  2080 + NSLog(@"未知错误");
  2081 + break;
  2082 + }
  2083 + });
  2084 + }];
  2085 + } else {
  2086 + if (failure) {
  2087 + NSString *errorMessage = [NSString stringWithFormat:@"当前设备不支持该预设:%@", presetName];
  2088 + failure(errorMessage, nil);
  2089 + }
  2090 + }
  2091 +}
  2092 +
  2093 +
  2094 +/// 取得asset类型
  2095 +- (CNAssetModelMediaType)getAssetType:(id)asset {
  2096 +
  2097 + CNAssetModelMediaType type = CNAssetModelMediaTypePhoto;
  2098 + if ([asset isKindOfClass:[PHAsset class]]) {
  2099 + PHAsset *phAsset = (PHAsset *)asset;
  2100 + if (phAsset.mediaType == PHAssetMediaTypeVideo) type = CNAssetModelMediaTypeVideo;
  2101 + else if (phAsset.mediaType == PHAssetMediaTypeAudio) type = CNAssetModelMediaTypeAudio;
  2102 + else if (phAsset.mediaType == PHAssetMediaTypeImage) {
  2103 + if (kiOS9_1Later) {
  2104 + if (@available(iOS 9.1, *)) {
  2105 + if (phAsset.mediaSubtypes == PHAssetMediaSubtypePhotoLive)
  2106 + {
  2107 + type = CNAssetModelMediaTypeLivePhoto;
  2108 + }
  2109 + } else {
  2110 + // Fallback on earlier versions
  2111 + }
  2112 + }
  2113 + // Gif
  2114 + if ([[phAsset valueForKey:@"filename"] hasSuffix:@"GIF"]) {
  2115 + type = CNAssetModelMediaTypePhotoGif;
  2116 + }
  2117 + }
  2118 + } else {
  2119 + if ([[asset valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypeVideo]) {
  2120 + type = CNAssetModelMediaTypeVideo;
  2121 + }
  2122 + }
  2123 + return type;
  2124 +}
  2125 +
  2126 +#pragma mark - 七牛短视频设置方法
  2127 +
  2128 +/// 短视频分辨率转码导出
  2129 ++ (void )zipVideoWithAsset:(id) asset outputPath:(NSString *)outputPath limitType:(AppPhototLimitType)limitType progressCount:(void(^)(float progress)) progressCount success:(void(^)(NSURL * url))success failure:(void(^)(void))failure {
  2130 +
  2131 + //取得url
  2132 + NSURL *url = [asset movieURL];
  2133 +
  2134 + NSInteger dataLInt = [NSData dataWithContentsOfURL:url].length;
  2135 + NSNumber *dataNumber = [NSNumber numberWithInteger:dataLInt];
  2136 + float dataL = [dataNumber floatValue];
  2137 + NSLog(@"转码前数据大小%f",dataL / (1024.0*1024.0));
  2138 + //编辑原始数据
  2139 + NSMutableDictionary *movieSettings = [[NSMutableDictionary alloc]init];
  2140 + AVAsset *avAsset = [AVAsset assetWithURL:url];
  2141 + movieSettings[PLSURLKey] = url;
  2142 + movieSettings[PLSAssetKey] = avAsset;
  2143 + movieSettings[PLSStartTimeKey] = [NSNumber numberWithFloat:0.f];//开始时间
  2144 + movieSettings[PLSDurationKey] = [NSNumber numberWithFloat:CMTimeGetSeconds(avAsset.duration)];//时长
  2145 + //设置进行压缩
  2146 + CGFloat start = [movieSettings[PLSStartTimeKey] floatValue];
  2147 + CGFloat duration = [movieSettings[PLSDurationKey] floatValue];
  2148 + NSLog(@"转码前输出时长:%f.2",duration);
  2149 + CMTimeRange timeRange = CMTimeRangeMake(CMTimeMake(start * 1000, 1000), CMTimeMake(duration * 1000, 1000));
  2150 + PLShortVideoTranscoder *shortVideoTranscoder = [[PLShortVideoTranscoder alloc] initWithURL:url];
  2151 +
  2152 + NSString *editOutputPath = @"";
  2153 + NSDateFormatter *formater = [[NSDateFormatter alloc] init];
  2154 + [formater setDateFormat:@"yyyy-MM-dd-HH:mm:ss-SSS"];
  2155 + NSInteger rand = random();
  2156 + NSString *filaName = [NSString stringWithFormat:@"output-%@_fileType=videoType_%ld.mp4",[formater stringFromDate:[NSDate date]],rand];
  2157 +
  2158 + editOutputPath = [[CNLiveUploadManager createVideoFolderOutputPath:outputPath] stringByAppendingString:filaName];
  2159 +
  2160 + NSLog(@"输出转码前视频路径%@",editOutputPath);
  2161 + shortVideoTranscoder.outputURL = [NSURL fileURLWithPath:editOutputPath];
  2162 + shortVideoTranscoder.outputFileType = PLSFileTypeMPEG4;
  2163 + shortVideoTranscoder.outputFilePreset = [CNLiveUploadManager presetWithVideoLimitType:limitType url:url dataL:dataL];//分辨率
  2164 + shortVideoTranscoder.bitrate = [CNLiveUploadManager bitrateWithPreset:shortVideoTranscoder.outputFilePreset avAsset:avAsset url:url dataL:dataL];
  2165 + shortVideoTranscoder.timeRange = timeRange;
  2166 + shortVideoTranscoder.rotateOrientation = PLSPreviewOrientationPortrait; //视频显示
  2167 + shortVideoTranscoder.videoSelectedRect = CGRectZero; //视频剪裁区域
  2168 + shortVideoTranscoder.videoFrameRate = 0; //帧率
  2169 + //成功
  2170 + [shortVideoTranscoder setCompletionBlock:^(NSURL *url){
  2171 + NSLog(@"输出转码后视频路径%@",url.path);
  2172 + NSLog(@"输出转码后数据大小%ld",[NSData dataWithContentsOfURL:url].length / (1024*1024));
  2173 + dispatch_async(dispatch_get_main_queue(), ^{
  2174 + !success ? : success(url);
  2175 + });
  2176 +
  2177 + }];
  2178 +
  2179 + //失败
  2180 + [shortVideoTranscoder setFailureBlock:^(NSError *error){
  2181 + NSLog(@"输出错误%@",error);
  2182 + dispatch_async(dispatch_get_main_queue(), ^{
  2183 + !failure ? : failure();
  2184 + });
  2185 +
  2186 + }];
  2187 +
  2188 + [shortVideoTranscoder setProcessingBlock:^(float progress){
  2189 + // 更新压缩进度的 UI
  2190 +
  2191 + NSLog(@"transCoding progress: %f", progress);
  2192 + !progressCount ? : progressCount(progress);
  2193 + }];
  2194 +
  2195 + [shortVideoTranscoder startTranscoding];
  2196 +
  2197 +
  2198 +}
  2199 +
  2200 +
  2201 +/// 新短视频分辨率转码导出
  2202 ++ (void )zipNewVideoWithAsset:(id) asset outputPath:(NSString *)outputPath limitType:(AppPhototLimitType)limitType progressCount:(void(^)(float progress)) progressCount success:(void(^)(NSURL * url))success failure:(void(^)(void))failure {
  2203 +
  2204 + //取得url
  2205 + NSURL *url = [asset movieURL];
  2206 + if (!url) {
  2207 + !failure ? : failure();
  2208 + return;
  2209 + }
  2210 + NSInteger dataLInt = [NSData dataWithContentsOfURL:url].length;
  2211 + NSNumber *dataNumber = [NSNumber numberWithInteger:dataLInt];
  2212 + float dataL = [dataNumber floatValue];
  2213 + NSLog(@"转码前数据大小%f",dataL / (1024.0*1024.0));
  2214 + //编辑原始数据
  2215 + NSMutableDictionary *movieSettings = [[NSMutableDictionary alloc]init];
  2216 + AVAsset *avAsset = [AVAsset assetWithURL:url];
  2217 + movieSettings[PLSURLKey] = url;
  2218 + movieSettings[PLSAssetKey] = avAsset;
  2219 + movieSettings[PLSStartTimeKey] = [NSNumber numberWithFloat:0.f];//开始时间
  2220 + movieSettings[PLSDurationKey] = [NSNumber numberWithFloat:CMTimeGetSeconds(avAsset.duration)];//时长
  2221 + //设置进行压缩
  2222 + CGFloat start = [movieSettings[PLSStartTimeKey] floatValue];
  2223 + CGFloat duration = [movieSettings[PLSDurationKey] floatValue];
  2224 + NSLog(@"转码前输出时长:%f.2",duration);
  2225 + CMTimeRange timeRange = CMTimeRangeMake(CMTimeMake(start * 1000, 1000), CMTimeMake(duration * 1000, 1000));
  2226 + PLShortVideoTranscoder *shortVideoTranscoder = [[PLShortVideoTranscoder alloc] initWithURL:url];
  2227 +
  2228 + NSString *editOutputPath = @"";
  2229 + NSDateFormatter *formater = [[NSDateFormatter alloc] init];
  2230 + [formater setDateFormat:@"yyyy-MM-dd-HH:mm:ss-SSS"];
  2231 + NSInteger rand = random();
  2232 + NSString *filaName = [NSString stringWithFormat:@"output-%@_fileType=videoType_%ld.mp4",[formater stringFromDate:[NSDate date]],rand];
  2233 + editOutputPath = [[CNLiveUploadManager createVideoFolderOutputPath:outputPath] stringByAppendingString:filaName];
  2234 +
  2235 + NSLog(@"输出转码前视频路径%@",outputPath);
  2236 + shortVideoTranscoder.outputURL = [NSURL fileURLWithPath:outputPath];
  2237 + shortVideoTranscoder.outputFileType = PLSFileTypeMPEG4;
  2238 + shortVideoTranscoder.outputFilePreset = [CNLiveUploadManager presetWithVideoLimitType:limitType url:url dataL:dataL];//分辨率
  2239 + shortVideoTranscoder.bitrate = [CNLiveUploadManager bitrateWithPreset:shortVideoTranscoder.outputFilePreset avAsset:avAsset url:url dataL:dataL];
  2240 + shortVideoTranscoder.timeRange = timeRange;
  2241 + shortVideoTranscoder.rotateOrientation = PLSPreviewOrientationPortrait; //视频显示
  2242 + shortVideoTranscoder.videoSelectedRect = CGRectZero; //视频剪裁区域
  2243 + shortVideoTranscoder.videoFrameRate = 0; //帧率
  2244 +
  2245 + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
  2246 + //成功
  2247 + [shortVideoTranscoder setCompletionBlock:^(NSURL *url){
  2248 + NSLog(@"输出转码后视频路径%@",url.path);
  2249 + NSLog(@"输出转码后数据大小%ld",[NSData dataWithContentsOfURL:url].length / (1024*1024));
  2250 + !success ? : success(url);
  2251 + dispatch_semaphore_signal(semaphore);
  2252 +
  2253 + }];
  2254 +
  2255 + //失败
  2256 + [shortVideoTranscoder setFailureBlock:^(NSError *error){
  2257 + NSLog(@"输出错误%@",error);
  2258 + !failure ? : failure();
  2259 + dispatch_semaphore_signal(semaphore);
  2260 +
  2261 + }];
  2262 +
  2263 + [shortVideoTranscoder setProcessingBlock:^(float progress){
  2264 + // 更新压缩进度的 UI
  2265 +
  2266 + NSLog(@"transCoding progress: %f", progress);
  2267 + !progressCount ? : progressCount(progress);
  2268 + }];
  2269 +
  2270 + [shortVideoTranscoder startTranscoding];
  2271 + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
  2272 +
  2273 +
  2274 +}
  2275 +
  2276 +/// 根据限制获取视频分辨率
  2277 ++ (PLSFilePreset)presetWithVideoLimitType:(AppPhototLimitType)limitType url:(NSURL *)url dataL:(float)dataL{
  2278 +
  2279 + NSLog(@"1输出转码前数据长度%f",(dataL/(1024.0*1024)));
  2280 + if (limitType == AppPhototLimitTypeChat) {//聊天
  2281 + if (dataL > kCNUploadSize20MB) {
  2282 + return PLSFilePreset640x480;
  2283 + }else {
  2284 + return PLSFilePreset960x540;
  2285 + }
  2286 +
  2287 + }else if (limitType == AppPhototLimitTypeFriendsCircle) {//朋友圈
  2288 + if (dataL > kCNUploadSize30MB) {
  2289 + return PLSFilePreset640x480;
  2290 + }else {
  2291 + return PLSFilePreset960x540;
  2292 + }
  2293 +
  2294 + }else if (limitType == AppPhototLimitTypeSweepCode) {//扫码
  2295 + if (dataL > kCNUploadSize30MB) {
  2296 + return PLSFilePreset640x480;
  2297 + }else {
  2298 + return PLSFilePreset960x540;
  2299 + }
  2300 + }else if (limitType == AppPhototLimitTypeTarentoComment) {//评论
  2301 + if (dataL > kCNUploadSize30MB) {
  2302 + return PLSFilePreset640x480;
  2303 + }else {
  2304 + return PLSFilePreset960x540;
  2305 + }
  2306 +
  2307 + }else {
  2308 + if (dataL > kCNUploadSize30MB) {//其他
  2309 + return PLSFilePreset640x480;
  2310 + }else {
  2311 + return PLSFilePreset960x540;
  2312 + }
  2313 + }
  2314 +
  2315 +}
  2316 +
  2317 +///根据分辨力设置码率
  2318 ++ (float)bitrateWithPreset:(PLSFilePreset)perset avAsset:(AVAsset *)avAsset url:(NSURL *)url dataL:(float)dataL{
  2319 +
  2320 + float bitrate = avAsset.pls_bitrate;
  2321 +
  2322 + if (perset == PLSFilePresetLowQuality) {
  2323 + return 700 * 1000;
  2324 + }else if (perset == PLSFilePresetMediumQuality) {
  2325 + return 3000 * 1000;
  2326 + }else if (perset == PLSFilePresetHighestQuality) {
  2327 + return 6000 * 1000;
  2328 + }else {
  2329 + if (dataL > 150*1024*1024) {
  2330 + float scale = (20*1024*1024)/dataL;
  2331 + if (bitrate *scale > 300 * 1000) {
  2332 + return 200 *1000;
  2333 + }else {
  2334 + return bitrate *scale;
  2335 + }
  2336 + }else if (dataL > 50*1024*1024) {
  2337 + float scale = (25*1024*1024)/dataL;
  2338 + if (bitrate *scale > 400 * 1000) {
  2339 + return 400 *1000;
  2340 + }else {
  2341 + return bitrate *scale;
  2342 + }
  2343 +
  2344 + }else if (dataL > 40*1024*1024) {
  2345 + if (bitrate *0.4 > 450 * 1000) {
  2346 + return 450 *1000;
  2347 + }else {
  2348 + return bitrate *0.40;
  2349 + }
  2350 +
  2351 + }else if (dataL > 30*1024*1024) {
  2352 +
  2353 + if (bitrate *0.60 > 700 * 1000) {
  2354 + return 550 *1000;
  2355 + }else {
  2356 + return bitrate *0.60;
  2357 + }
  2358 + }else if (dataL > 20*1024*1024) {
  2359 +
  2360 + return bitrate *0.80;
  2361 + }else if (dataL > 10*1024*1024) {
  2362 +
  2363 + return bitrate *0.9;
  2364 + }else {
  2365 + return bitrate;
  2366 + }
  2367 + }
  2368 +
  2369 +}
  2370 +
  2371 +
  2372 +#pragma mark - 金山
  2373 +
  2374 +
  2375 +@end
  2376 +
  2377 +@implementation CNLiveUploadModel
  2378 +
  2379 +- (instancetype)init
  2380 +{
  2381 + self = [super init];
  2382 + if (self) {
  2383 +
  2384 + _code = @"";
  2385 + _index = 0;
  2386 + _imageUrl = @"";
  2387 + _file = @"";
  2388 + _message = @"";
  2389 + _image = nil;
  2390 + _imageW = 0;
  2391 + _imageH = 0;
  2392 + _asset = nil;
  2393 + _info = nil;
  2394 + _key = @"";
  2395 + _resp = nil;
  2396 + _responseObject = nil;
  2397 +
  2398 + }
  2399 + return self;
  2400 +}
  2401 +
  2402 +
  2403 +
  2404 +
  2405 +@end
  2406 +
  2407 +
... ...
CNLiveUploadManager/Classes/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 DEPRECATED_MSG_ATTRIBUTE("Please use CNLiveNetworking");
  32 +
  33 +@end
... ...
CNLiveUploadManager/Classes/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 <AFNetworking/AFNetworking.h>
  11 +#import <CNLiveRequestBastKit/CNLiveNetworking.h>
  12 +#import <MJExtension/MJExtension.h>
  13 +#import <YYKit/YYKit.h>
  14 +
  15 +static NSString *errorCode = @"errorCode";
  16 +static NSString *errorMessage = @"errorMessage";
  17 +static NSString *requestData = @"data";
  18 +
  19 +@interface HttpService ()
  20 +{
  21 + AFHTTPSessionManager *_dataSessionManager;
  22 +}
  23 +
  24 +@end
  25 +
  26 +@implementation HttpService
  27 +
  28 +#pragma mark -
  29 +#pragma mark - SINGLETON
  30 +
  31 +static HttpService * __singleton__;
  32 +
  33 ++ (HttpService *)service {
  34 + static dispatch_once_t predicate;
  35 + dispatch_once( &predicate, ^{ __singleton__ = [[[self class] alloc] init]; } );
  36 + return __singleton__;
  37 +}
  38 +
  39 +#pragma mark -
  40 +#pragma mark - Init
  41 +
  42 +- (instancetype)init {
  43 + self = [super init];
  44 + if (self) {
  45 + [self initManagers];
  46 + }
  47 + return self;
  48 +}
  49 +
  50 +/** 所有网络请求的基础 */
  51 +- (NSURLSessionDataTask *)sendRequestWithHttpMethod:(HTTP_REQUEST_METHOD)method URLPath:(NSString *)pathStr parameters:(id)parameters isCache:(BOOL)isCache CheckParam:(NSArray *)checkParam completionHandler:(completionHandler)completionHandler
  52 +{
  53 + CNLiveRequestMethod requestMethod = method == E_HTTP_REQUEST_METHOD_POST ? CNLiveRequestMethodPOST : CNLiveRequestMethodGET;
  54 + CNLiveNetworkCacheType networkCacheType = isCache ? CNLiveNetworkCacheTypeCacheNetwork : CNLiveNetworkCacheTypeNetworkOnly;
  55 + [CNLiveNetworking setupDome:NO];
  56 + [CNLiveNetworking setupShowDataResult:NO];
  57 + [CNLiveNetworking setAllowRequestDefaultArgument:YES];
  58 + return (NSURLSessionDataTask *)[CNLiveNetworking requestNetworkWithMethod:requestMethod URLString:pathStr Param:parameters==nil?@{}:parameters CacheType:networkCacheType CompletionBlock:^(NSURLSessionTask *requestTask, id responseObject, NSError *error) {
  59 + NSDictionary * responseObjectDic = [responseObject mj_keyValues];
  60 +
  61 + if (error) {
  62 + if (completionHandler) completionHandler(responseObject, error);
  63 + return;
  64 + }
  65 + NSString *resultCode = [NSString stringWithFormat:@"%@", responseObjectDic[errorCode]];
  66 + NSError *err = nil;
  67 + id data = nil;
  68 + if([resultCode isEqualToString:@"0"]) {
  69 + data = responseObjectDic[requestData];
  70 + } else {
  71 + @try {
  72 + err = [[NSError alloc] initWithDomain:responseObjectDic[errorMessage] code:[resultCode integerValue] userInfo:nil];
  73 + } @catch (NSException *exception) {
  74 + err = [[NSError alloc] initWithDomain:@"接口异常" code:500 userInfo:nil];
  75 + }
  76 + }
  77 + if (completionHandler) completionHandler(data, err);
  78 + }];
  79 + /*
  80 + dispatch_async(dispatch_get_main_queue(), ^{
  81 + [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
  82 +
  83 + });
  84 + NSMutableDictionary *para = [CNLiveBusinessTools encryptionSignWithParameter:[NSMutableDictionary dictionaryWithDictionary:parameters] encryptionKey:APPKey];
  85 + NSString *urlStr = [[NSURL URLWithString:pathStr relativeToURL:_dataSessionManager.baseURL] absoluteString];
  86 + NSString *methodStr = [self stringWithMethod:method];
  87 +
  88 + if (completionHandler && isCache) {
  89 + [CNHttpLocalServer cacheForURL:urlStr parameters:para CheckParam:checkParam == nil ?@[]:checkParam withBlock:^(id<NSCoding> object) {
  90 + if (object != nil) completionHandler(object,nil);
  91 + }];
  92 + }
  93 + NSDictionary * dic = [CNHttpLocalServer cacheForURL:urlStr parameters:para CheckParam:checkParam == nil ?@[]:checkParam];
  94 +// [IMAPlatform sharedInstance].isConnected
  95 + if (![[[NSUserDefaults standardUserDefaults] objectForKey:CNConnectSuccNotification] boolValue] && dic == nil && completionHandler) {
  96 + completionHandler(nil,[NSError errorWithDomain:@"暂无网络" code:-1001 userInfo:nil]);
  97 + return nil;
  98 + };
  99 + NSMutableURLRequest *request = [_dataSessionManager.requestSerializer requestWithMethod:methodStr URLString:urlStr parameters:para error:nil];
  100 + __block NSURLSessionDataTask *task = nil;
  101 + task = [_dataSessionManager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {//
  102 + [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
  103 + NSError *err = nil;
  104 + id data = nil;
  105 + if(error ) {
  106 + err = error;
  107 +#if DEBUG
  108 + [[CNNetworkLogManager defaultManager] showErrorLogWithResponse:error];
  109 +#else
  110 + if (error.code == 500 || error.code == 404) return;
  111 +#endif
  112 + }else {
  113 + NSDictionary * responseObjectDic = [responseObject mj_keyValues];
  114 +
  115 + NSString *resultCode = [NSString stringWithFormat:@"%@", responseObjectDic[errorCode]];
  116 +
  117 + if([resultCode isEqualToString:@"0"]) {
  118 + data = responseObjectDic[requestData];
  119 + } else {
  120 + @try {
  121 + err = [[NSError alloc] initWithDomain:responseObjectDic[errorMessage] code:[resultCode integerValue] userInfo:nil];
  122 + } @catch (NSException *exception) {
  123 + NSLog(@"获取到的异常是===>%@ ===>%@",exception,urlStr);
  124 + err = [[NSError alloc] initWithDomain:@"接口异常" code:500 userInfo:nil];
  125 + }
  126 + }
  127 + }
  128 +
  129 + dispatch_async(dispatch_get_main_queue(), ^{
  130 + completionHandler(data, err);
  131 + if ((data || [CNHttpLocalServer cacheForURL:urlStr parameters:para CheckParam:checkParam == nil ?@[]:checkParam] == nil) && isCache) {
  132 + [CNHttpLocalServer setCache:data URL:urlStr parameters:para CheckParam:checkParam == nil ? @[]:checkParam];
  133 + }
  134 + });
  135 +
  136 + }];
  137 + [task resume];
  138 + return task;
  139 + */
  140 +}
  141 +
  142 +- (NSString *)stringWithMethod:(HTTP_REQUEST_METHOD)method {
  143 + switch (method) {
  144 + case E_HTTP_REQUEST_METHOD_GET: return @"GET"; break;
  145 + case E_HTTP_REQUEST_METHOD_POST: return @"POST"; break;
  146 + default:
  147 + break;
  148 + }
  149 + return @"";
  150 +}
  151 +/** 清除所有任务 */
  152 +- (void)cleanAllTask {
  153 + [self invalidateManagers];
  154 + [self initManagers];
  155 + [CNLiveNetworking cancelAll];
  156 +}
  157 +
  158 +- (void)invalidateManagers {
  159 +// [_dataSessionManager invalidateSessionCancelingTasks:YES];
  160 +
  161 +}
  162 +
  163 +#pragma mark -
  164 +#pragma mark - Ptavite Methods
  165 +- (void)initManagers {
  166 +
  167 +// _dataSessionManager = [[AFHTTPSessionManager alloc] initWithBaseURL:nil];
  168 +// [_dataSessionManager setRequestSerializer:[AFHTTPRequestSerializer serializer]];
  169 +// [_dataSessionManager.requestSerializer setTimeoutInterval:kTimeoutInterval];
  170 +//// [_dataSessionManager setResponseSerializer:[AFJSONResponseSerializer serializer]];
  171 +//// _dataSessionManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html",@"image/jpeg",@"text/javascript",@"application/json",@"text/json",@"text/plain",nil];
  172 +// _dataSessionManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/html",@"text/json", @"text/javascript", nil];
  173 +
  174 +
  175 +}
  176 +
  177 +@end
... ...
CNLiveUploadManager/_Pods.xcodeproj deleted 120000 → 0
1   -Example/Pods/Pods.xcodeproj
2 0 \ No newline at end of file
CNLiveUploadManager/Example/CNLiveUploadManager.xcodeproj/project.pbxproj renamed to Example/CNLiveUploadManager.xcodeproj/project.pbxproj
CNLiveUploadManager/Example/CNLiveUploadManager.xcodeproj/xcshareddata/xcschemes/CNLiveUploadManager-Example.xcscheme renamed to Example/CNLiveUploadManager.xcodeproj/xcshareddata/xcschemes/CNLiveUploadManager-Example.xcscheme
CNLiveUploadManager/Example/CNLiveUploadManager/Base.lproj/LaunchScreen.storyboard renamed to Example/CNLiveUploadManager/Base.lproj/LaunchScreen.storyboard
CNLiveUploadManager/Example/CNLiveUploadManager/Base.lproj/Main.storyboard renamed to Example/CNLiveUploadManager/Base.lproj/Main.storyboard
CNLiveUploadManager/Example/CNLiveUploadManager/CNLiveAppDelegate.h renamed to Example/CNLiveUploadManager/CNLiveAppDelegate.h
CNLiveUploadManager/Example/CNLiveUploadManager/CNLiveAppDelegate.m renamed to Example/CNLiveUploadManager/CNLiveAppDelegate.m
CNLiveUploadManager/Example/CNLiveUploadManager/CNLiveUploadManager-Info.plist renamed to Example/CNLiveUploadManager/CNLiveUploadManager-Info.plist
CNLiveUploadManager/Example/CNLiveUploadManager/CNLiveUploadManager-Prefix.pch renamed to Example/CNLiveUploadManager/CNLiveUploadManager-Prefix.pch
CNLiveUploadManager/Example/CNLiveUploadManager/CNLiveViewController.h renamed to Example/CNLiveUploadManager/CNLiveViewController.h
CNLiveUploadManager/Example/CNLiveUploadManager/CNLiveViewController.m renamed to Example/CNLiveUploadManager/CNLiveViewController.m
CNLiveUploadManager/Example/CNLiveUploadManager/Images.xcassets/AppIcon.appiconset/Contents.json renamed to Example/CNLiveUploadManager/Images.xcassets/AppIcon.appiconset/Contents.json
CNLiveUploadManager/Example/CNLiveUploadManager/en.lproj/InfoPlist.strings renamed to Example/CNLiveUploadManager/en.lproj/InfoPlist.strings
CNLiveUploadManager/Example/CNLiveUploadManager/main.m renamed to Example/CNLiveUploadManager/main.m
CNLiveUploadManager/Example/Podfile renamed to Example/Podfile
CNLiveUploadManager/Example/Tests/Tests-Info.plist renamed to Example/Tests/Tests-Info.plist
CNLiveUploadManager/Example/Tests/Tests-Prefix.pch renamed to Example/Tests/Tests-Prefix.pch
CNLiveUploadManager/Example/Tests/Tests.m renamed to Example/Tests/Tests.m
CNLiveUploadManager/Example/Tests/en.lproj/InfoPlist.strings renamed to Example/Tests/en.lproj/InfoPlist.strings
CNLiveUploadManager/LICENSE renamed to LICENSE
CNLiveUploadManager/README.md renamed to README.md
_Pods.xcodeproj 0 → 120000
  1 +Example/Pods/Pods.xcodeproj
0 2 \ No newline at end of file
... ...