目錄
集成
# 阿里云
pod 'AliyunOSSiOS', '~> 2.6.0'
#import <AliyunOSSiOS/AliyunOSSiOS.h>
封裝成工具類,方便使用
YTTool.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "AliyunOSSiOS/OSSService.h"
typedef void(^ResultBlock)(BOOL isOK,NSString *url);
typedef void(^Progress)(float progress);
typedef void(^ResultBlockT)(BOOL isOK,NSArray<NSString *> *imgNameArr);
@interface YTTool : NSObject
/**
* 異步上傳 單張圖片
*
* @param image 要上傳的圖片
* @param progressBlock 上傳圖片進度
* @param resultBlock 上傳圖片結(jié)果
*/
+(void)uploadPhotoAsync:(UIImage *)image progress:(Progress)progressBlock resultBlock:(ResultBlock)resultBlock;
/**
* 同步上傳 單張圖片
*
* @param image 要上傳的圖片
*
* @return 上傳成功后返回的Url
*/
+(NSString *)uploadPhotoSync:(UIImage *)image progress:(Progress)progressBlock;
/**
* 異步上傳 多張圖片
*
* @param imageArr 要上傳的圖片數(shù)組
* @param progressBlock 上傳圖片進度
* @param resultBlock 上傳圖片結(jié)果
* @param isAsync 是否異步
*/
+(void)uploadPhotos:(NSArray<UIImage *> *)imageArr progress:(Progress)progressBlock resultBlock:(ResultBlockT)resultBlock isAsync:(BOOL)isAsync;
@end
YTTool.m
#import "YTTool.h"
// AccessKey
NSString * const AccessKey = @"LTAIULEB2J0Otax0";
// SecretKey
NSString * const SecretKey = @"zXXeirYoRw1qdd4ZRLrhwkOCEriw0R";
// 與OSS文件夾名對應(yīng)
NSString * const PUBLIC_BUCKET = @"kachamao";
//
NSString * const ENDPOINTIMAGE = @"http://oss-cn-shanghai.aliyuncs.com";
// 子文件夾
NSString * const OBJECT_KEY = @"CaChaCat_App_img";
//
NSString * const MultipartUploadObjectKey = @"multipartUploadObject";
//
CGFloat const kPix = 750;
// 修飾全局,作用域僅限于本類
static OSSClient * client;
@implementation YTTool
// 初始化OSS客戶端
+ (void)initOSSClient{
// 1. credential
id<OSSCredentialProvider> credential = [[OSSPlainTextAKSKPairCredentialProvider alloc] initWithPlainTextAccessKey:AccessKey secretKey:SecretKey];
// 2. OSSClient配置參數(shù)
OSSClientConfiguration *config = [OSSClientConfiguration new];
// 設(shè)置 是否開啟后臺傳輸
config.enableBackgroundTransmitService = NO;
// 設(shè)置 最大重試次數(shù)
config.maxRetryCount = 3;
// 設(shè)置 請求超時時間
config.timeoutIntervalForRequest = 20;
// 設(shè)置 單個object下載最長持續(xù)時間
config.timeoutIntervalForResource = 24 * 60 * 60;
// 3. 初始OSS化客戶端
client = [[OSSClient alloc]initWithEndpoint:ENDPOINTIMAGE credentialProvider:credential clientConfiguration:config];
}
// 異步上傳 單張圖片
+ (void)uploadPhotoAsync:(UIImage *)image progress:(Progress)progressBlock resultBlock:(ResultBlock)resultBlock{
OSSPutObjectRequest *put=[self getPutWithImage:image progress:progressBlock];
// 2.上傳
OSSTask *putTast = [client putObject:put];
[putTast continueWithBlock:^id _Nullable(OSSTask * _Nonnull task) {
if (!task.error){ // 上傳成功
NSLog(@"上傳成功");
dispatch_async(dispatch_get_main_queue(), ^{
// 上傳成功后的圖片UrlStr
NSString *str=[[ENDPOINTIMAGE componentsSeparatedByString:@"http://"] lastObject];
NSString *urlString=[NSString stringWithFormat:@"https://%@.%@/%@",PUBLIC_BUCKET,str,put.objectKey];
resultBlock(YES,urlString);
});
}else{ // 上傳失敗
NSLog(@"上傳失敗:%@",task.error);
dispatch_async(dispatch_get_main_queue(), ^{
resultBlock(NO,nil);
});
}
return nil;
}];
}
// 同步上傳 單張圖片
+ (NSString *)uploadPhotoSync:(UIImage *)image progress:(Progress)progressBlock{
OSSPutObjectRequest *put=[self getPutWithImage:image progress:progressBlock];
// 2.上傳
OSSTask *putTast = [client putObject:put];
[[putTast continueWithBlock:^id _Nullable(OSSTask * _Nonnull task) {
if (!task.error){
NSLog(@"上傳成功");
}else{
NSLog(@"上傳失敗:%@",task.error);
}
return nil;
}] waitUntilFinished];
// 上傳成功后的圖片UrlStr
NSString *str=[[ENDPOINTIMAGE componentsSeparatedByString:@"http://"] lastObject];
NSString *urlString=[NSString stringWithFormat:@"https://%@.%@/%@",PUBLIC_BUCKET,str,put.objectKey];
return urlString;
}
// 創(chuàng)建請求 OSSPutObjectRequest
+(OSSPutObjectRequest *)getPutWithImage:(UIImage *)image progress:(Progress)progressBlock{
// 0.初始化客戶端
[self initOSSClient];
// 1.上傳請求
OSSPutObjectRequest *put = [OSSPutObjectRequest new];
// 1.1.設(shè)置bucketName (文件夾名,與OSS對應(yīng))
put.bucketName = PUBLIC_BUCKET;
// 1.2.文件名路徑
NSTimeInterval timeInterval =[[NSDate date] timeIntervalSince1970];
NSString *objectName = [NSString stringWithFormat:@"%@/%@_img_%d.png",[self dirPath],[self timeStringWithDataTimeToDate:timeInterval],((arc4random()% 100000000) + 10000)];
put.objectKey = objectName;
// 1.3.上傳對象(圖片data)
put.uploadingData = [self imageCompressForSize:image targetPx:kPix];
// 1.4.上傳進度
put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
float progress = (float)totalByteSent/totalBytesExpectedToSend;
progressBlock(progress);
};
return put;
}
// 上傳多張圖片
+(void)uploadPhotos:(NSArray<UIImage *> *)imageArr progress:(Progress)progressBlock resultBlock:(ResultBlockT)resultBlock isAsync:(BOOL)isAsync{
// 0.初始化客戶端
[self initOSSClient];
// 1.線程隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 1.1最大線程數(shù)
queue.maxConcurrentOperationCount = imageArr.count;
//
NSMutableArray *callBackNames = [NSMutableArray array];
int i = 0;
for (UIImage *image in imageArr){
if (image){
// 線程
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
// 1.上傳請求
OSSPutObjectRequest *put = [OSSPutObjectRequest new];
// 1.1.設(shè)置bucketName (文件夾名,與OSS對應(yīng))
put.bucketName = PUBLIC_BUCKET;
// 1.2.文件名+路徑
NSTimeInterval timeInterval =[[NSDate date] timeIntervalSince1970];
NSString *objectName = [NSString stringWithFormat:@"%@/%@_img_%d.png",[self dirPath],[self timeStringWithDataTimeToDate:timeInterval],((arc4random()% 100000000) + 10000)];
put.objectKey = objectName;
// iconName
NSString *encodingString = [[NSString stringWithFormat:@"http://kachamao.oss-cn-shanghai.aliyuncs.com/%@",objectName]stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
[callBackNames addObject: encodingString];
// 1.3.上傳對象(內(nèi)存中)
put.uploadingData = [self imageCompressForSize:image targetPx:kPix];
//
OSSTask * putTask = [client putObject:put];
[putTask continueWithBlock:^id(OSSTask *task){
if (task.error){
OSSLogError(@"%@", task.error);
}
OSSPutObjectResult * result = task.result;
NSLog(@"Result - requestId: %@, headerFields: %@",
result.requestId,
result.httpResponseHeaderFields);
return nil;
}]; // 阻塞直到上傳完成
if (isAsync) {
if (image == imageArr.lastObject) {
NSLog(@"upload object finished!");
if (resultBlock) {
resultBlock(true,callBackNames);
}
}
}
}];
if (queue.operations.count != 0) {
[operation addDependency:queue.operations.lastObject];
}
[queue addOperation:operation];
}
i++;
}
if (!isAsync) {
[queue waitUntilAllOperationsAreFinished];
if (resultBlock) {
if (resultBlock) {
resultBlock(true,[NSArray arrayWithArray:callBackNames]);
}
}
}
}
// 文件路徑(會在oss官網(wǎng)上生成文件夾路徑)
+ (NSString *)dirPath{
NSDateFormatter *formater = [NSDateFormatter new];
[formater setDateFormat:@"/yyyy/MM/yyyMMdd"];
NSString *str = [formater stringFromDate:[NSDate date]];
return [[OBJECT_KEY mutableCopy] stringByAppendingString:str];
}
/**
圖片壓縮的處理邏輯:
一 尺寸壓縮(一般參照像素為1280)
a. 寬高均<=1280px時 圖片尺寸保持不變
b. 寬高均>1280px時 圖片寬高比<=2,則將圖片寬或者高取大的等比壓縮至1280px; 圖片寬高比>2時,則寬或者高取小的等比壓縮至1280px;
c. 寬或高某一個>1280px,另一個<1280px時 圖片寬高比>2時,則寬高尺寸不變;圖片寬高比≤2時,則將圖片寬或者高取大的等比壓縮至1280px.
二 質(zhì)量壓縮
一般壓縮在90%
*/
#pragma mark -- 圖片壓縮方法
+ (NSData *)imageCompressForSize:(UIImage *)sourceImage targetPx:(NSInteger)targetPx{
//
BOOL drawImge = NO; // 是否需要重繪圖片 默認是NO
CGFloat scaleFactor = 0.0; // 壓縮比例
CGFloat scaledWidth = targetPx; // 壓縮后的寬度 默認是參照像素1280px
CGFloat scaledHeight = targetPx; // 壓縮后的高度 默認是參照像素1280px
// 壓縮尺寸
// 新圖片(尺寸壓縮后的)
UIImage *newImage = nil;
// 原size
CGSize imageSize = sourceImage.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;
// 判斷尺寸
if (width < targetPx && height < targetPx) { // a.寬高均<=參照像素時:尺寸不變
newImage = sourceImage;
}else if (width > targetPx && height > targetPx) { // b.寬或高均>1280px時
drawImge = YES;
CGFloat factor = width / height;
if (factor <= 2) { // b.1圖片寬高比≤2,則將圖片寬或者高取大的等比壓縮至1280px
if (width > height) {
scaleFactor = targetPx / width;
} else {
scaleFactor = targetPx / height;
}
} else { // b.2圖片寬高比>2時,則寬或者高取小的等比壓縮至1280px
if (width > height) {
scaleFactor = targetPx / height;
} else {
scaleFactor = targetPx / width;
}
}
}else if (width > targetPx && height < targetPx ) { // c.寬高一個>1280px,另一個<1280px 寬大于1280
if (width / height > 2) {
newImage = sourceImage;
} else {
drawImge = YES;
scaleFactor = targetPx / width;
}
}else if (width < targetPx && height > targetPx) { // c.寬高一個>1280px,另一個<1280px 高大于1280
if (height / width > 2) {
newImage = sourceImage;
} else {
drawImge = YES;
scaleFactor = targetPx / height;
}
}
if (drawImge == YES) { // 圖片需要重繪 按新寬高壓縮重繪圖片
scaledWidth = width * scaleFactor;
scaledHeight = height * scaleFactor;
UIGraphicsBeginImageContext(CGSizeMake(scaledWidth, scaledHeight));
[sourceImage drawInRect:CGRectMake(0, 0, scaledWidth,scaledHeight)];
newImage =UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
if (newImage == nil) {
newImage = sourceImage;
}
// 質(zhì)量壓縮(圖片>200kb 時)
NSData * scaledImageData = nil;
if (UIImageJPEGRepresentation(newImage, 1) == nil) {
scaledImageData = UIImagePNGRepresentation(newImage);
}else{
scaledImageData = UIImageJPEGRepresentation(newImage, 1);
if (scaledImageData.length >= 1024 * 200) {
scaledImageData = UIImageJPEGRepresentation(newImage, 0.5);
}
}
return scaledImageData;
}
// yyyy-MM-dd 時間戳
+ (NSString *)timeStringWithDataTimeToDate:(NSTimeInterval)time{
//
NSDateFormatter *dateFormatter = nil;
if (dateFormatter == nil) {
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"YYYY_MM_dd_hh_mm_ss"];
}
NSString *string = [dateFormatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:(time)]];
return string;
}
@end