这段时间一直写关于小程序和Vue.js的文章,却忽略了自己的本职工作:IOS开发,听到IOS开发,貌似已经被这些容易上手的web端代替,但是,原生就是原生,它的页面流畅度及用户体验效果还是比较好的。在此,记录下用IOS 上传多张图片到阿里云的功能封装。
一.准备工作
2. 把demo中的AliyunOSSiOS.framework拖入工程
3.在控制器内引入头文件#import <AliyunOSSiOS/OSSService.h> (多次引入时放入全局引入)
4. 初始化阿里云对象@property (strong, nonatomic) OSSClient *client;
二.封装好的图片上传代码
AliyunOSSUpload.h文件
#import <Foundation/Foundation.h> #import <UIKit/UIKit.h> #define AliyunUpload [AliyunOSSUpload aliyunInit]typedef enum{ ENT_fileImageHeader,//头像 ENT_fileImageBody,//个人图片 ENT_fileImageProject,//门店图片 ENT_fileImageJs,//店员展示图片 ENT_fileItemImageBody,//门店项目图片 }FileType; @interface AliyunOSSUpload : NSObject +(AliyunOSSUpload *)aliyunInit; -(void)uploadImage:(NSArray*)imgArr FileDirectory:(FileType)type success:(void (^)(NSString *obj))success; @end
上图定义的枚举代表上传不同类型的图片,根据公司要求,做一个图片功能上的区分,以根据图片名称很清楚知道代表什么类型。
AliyunOSSUpload.m文件
#import <AliyunOSSiOS/OSSService.h> #import <AliyunOSSiOS/OSSCompat.h> #import "AliyunOSSUpload.h" NSString * const AccessKey = @"***"; NSString * const SecretKey = @"***"; NSString * const endPoint = @"https://oss-cn-qingdao.aliyuncs.com/"; OSSClient * client; @implementation AliyunOSSUpload static AliyunOSSUpload *_config; +(AliyunOSSUpload *)aliyunInit{ @synchronized(self){ if (_config==nil) { [OSSLog enableLog]; _config=[[AliyunOSSUpload alloc] init]; id<OSSCredentialProvider> credential = [[OSSPlainTextAKSKPairCredentialProvider alloc] initWithPlainTextAccessKey:AccessKey secretKey:SecretKey]; client = [[OSSClient alloc] initWithEndpoint:endPoint credentialProvider:credential]; } } return _config; } //上传多张图片 -(void)uploadImage:(NSArray*)imgArr FileDirectory:(FileType)type success:(void (^)(NSString *obj))success{ NSMutableArray *imgArray=[NSMutableArray new]; for (int i=0; i<imgArr.count; i++) { NSData* data; NSDictionary *imgDictionary = [imgArr objectAtIndex:i]; NSArray *imgValue = [imgDictionary allValues]; NSArray *imgKey = [imgDictionary allKeys]; UIImage *image1 = [imgValue objectAtIndex:0]; NSString *str = [imgKey objectAtIndex:0]; UIImage *image=[IHUtility rotateAndScaleImage:image1 maxResolution:(int)kScreenWidth*2]; OSSPutObjectRequest * put = [OSSPutObjectRequest new]; put.contentType=@"image/jpeg"; put.bucketName = @"yijiao"; NSString *imgName; if (type==ENT_fileImageHeader) { NSData *data1=UIImageJPEGRepresentation(image, 1); float length1 = [data1 length]/1024; if (length1<600) { data = UIImageJPEGRepresentation(image, 1); }else{ if ([IHUtility IsEnableWIFI]) { data = UIImageJPEGRepresentation(image, 0.6); }else{ data = UIImageJPEGRepresentation(image, 0.5); } } imgName=[NSString stringWithFormat:@"ios/header/header_%@.jpg",[IHUtility getTransactionID]]; }else if (type==ENT_fileImageBody){ NSData *data1=UIImageJPEGRepresentation(image, 1); float length1 = [data1 length]/1024; if (length1<600) { data = UIImageJPEGRepresentation(image, 1); }else{ data = UIImageJPEGRepresentation(image, 0.5); } imgName=[NSString stringWithFormat:@"ios/content/body_%@/%@.jpg",str,[IHUtility getNowTimeTimestamp]]; }else if (type==ENT_fileImageJs) { NSData *data1=UIImageJPEGRepresentation(image, 1); float length1 = [data1 length]/1024; if (length1<600) { data = UIImageJPEGRepresentation(image, 1); }else{ data = UIImageJPEGRepresentation(image, 0.5); } imgName=[NSString stringWithFormat:@"js/header/header_%@.jpg",[IHUtility getTransactionID]]; }else if (type==ENT_fileImageProject){ NSData *data1=UIImageJPEGRepresentation(image, 1); float length1 = [data1 length]/1024; if (length1<600) { data = UIImageJPEGRepresentation(image, 1); }else{ data = UIImageJPEGRepresentation(image, 0.5); } imgName=[NSString stringWithFormat:@"ios/storePicture/web_%@/%@.jpg",str,[IHUtility getNowTimeTimestamp]]; }else if (type==ENT_fileItemImageBody){ NSData *data1=UIImageJPEGRepresentation(image, 1); float length1 = [data1 length]/1024; if (length1<600) { data = UIImageJPEGRepresentation(image, 1); }else{ data = UIImageJPEGRepresentation(image, 0.5); } imgName=[NSString stringWithFormat:@"ios/web/itemBody_%@/%@.jpg",str,[IHUtility getNowTimeTimestamp]]; } put.objectKey = imgName; put.uploadingData = data; // 直接上传NSData put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend); }; NSString *imgWidth; NSString *imgHeigh; if (type==ENT_fileImageHeader) { imgWidth=[NSString stringWithFormat:@"%d",(int)kScreenWidth]; imgHeigh=[NSString stringWithFormat:@"%d",(int)kScreenWidth]; } else if (type==ENT_fileImageBody){ imgWidth=[NSString stringWithFormat:@"%lf",image.size.width]; imgHeigh=[NSString stringWithFormat:@"%lf",image.size.height]; } else if (type==ENT_fileImageJs){ imgWidth=[NSString stringWithFormat:@"%lf",image.size.width]; imgHeigh=[NSString stringWithFormat:@"%lf",image.size.height]; }else if (type==ENT_fileImageProject){ imgWidth=[NSString stringWithFormat:@"%lf",image.size.width]; imgHeigh=[NSString stringWithFormat:@"%lf",image.size.height]; }else if (type==ENT_fileItemImageBody){ imgWidth=[NSString stringWithFormat:@"%lf",image.size.width]; imgHeigh=[NSString stringWithFormat:@"%lf",image.size.height]; } NSDictionary *dic=[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"/%@",imgName],@"t_url", imgWidth,@"t_width", imgHeigh,@"t_height", nil]; [imgArray addObject:dic]; if (client==nil) { id<OSSCredentialProvider> credential = [[OSSPlainTextAKSKPairCredentialProvider alloc] initWithPlainTextAccessKey :AccessKey secretKey:SecretKey]; client = [[OSSClient alloc] initWithEndpoint:endPoint credentialProvider:credential]; } OSSTask * putTask = [client putObject:put]; [putTask continueWithBlock:^id(OSSTask *task) { if (!task.error) { NSLog(@"upload object success!"); if (type==ENT_fileImageHeader) { NSString *str=[NSString stringWithFormat:@"/%@",imgName]; success(str); } else if (type==ENT_fileImageBody){ if (i==imgArr.count-1) { NSString *str=[imgArray JSONRepresentation]; success(str); } }else if (type==ENT_fileImageJs){ success(imgName); } else if (type==ENT_fileImageProject){ if (i==imgArr.count-1) { NSString *str=[imgArray JSONRepresentation]; success(str); } }else if (type==ENT_fileItemImageBody){ success(imgName); } } else{ [YJTipView showBottomWithText:@"图片上传失败,请重试" bottomOffset:300 duration:1.5f]; NSLog(@"upload object failed, error: %@" , task.error); } return nil; }]; } }
详细讲解如下:
NSString * const AccessKey = @"***"; NSString * const SecretKey = @"***"; NSString * const endPoint = @"
参数AccessKey,SecretKey,endPoint 是注册阿里云账号后,从阿里云控制台拿到的数据,为安全起见,这几个数据最好放在自己的服务器上,前端从服务器上获取。
+(AliyunOSSUpload *)aliyunInit
因为OSSClient是OSS服务的iOS客户端,它为调用者提供了一系列的方法,用于和OSS服务进行交互。一般来说,全局内只需要保持一个OSSClient,用来调用各种操作。所以定义全局方法。
put.contentType=@"image/jpeg"; put.bucketName = @"yijiao"; put.objectKey = @"自己的数据";
contentType代表上传图片类型,也可上传视频video/mp4
bucketName代表储存文件的区域,就是放在阿里云服务器里的文件名。
objectKey代表存储在文件区域内的对象,即 阿里云返回的图片名。
put.uploadingData = self.imageData;//自己的NSData数据
因为阿里云不支持同时上传多张图片,所以我们在上传的时候用for语句来循环上传,uploadingData就是接受图片data数据。
put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) { NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend); //当前上传段长度、当前已经上传总长度、一共需要上传的总长度 };
阿里云提供了上传图片的总长度,及当前上传的长度,当我们有需要计算上传图片的进度的需求,就可以利用这些字段很容易的完成。
NSData *data1=UIImageJPEGRepresentation(image, 1); float length1 = [data1 length]/1024; if (length1<600) { data = UIImageJPEGRepresentation(image, 1); }else{ if ([IHUtility IsEnableWIFI]) { data = UIImageJPEGRepresentation(image, 0.6); }else{ data = UIImageJPEGRepresentation(image, 0.5); } }
上传图片时,有的图片比较大,我们需要按比例压缩下,上面代码就是压缩图片的方法。
图片旋转的方法如下:
+(UIImage *)rotateAndScaleImage:(UIImage *)image maxResolution:(NSInteger)maxResolution {
int kMaxResolution;
if (maxResolution <= 0)
kMaxResolution = 640;
else
kMaxResolution = (int)maxResolution;
CGImageRef imgRef = image.CGImage;
CGFloat width = CGImageGetWidth(imgRef);
CGFloat height = CGImageGetHeight(imgRef);
CGAffineTransform transform = CGAffineTransformIdentity;
CGRect bounds = CGRectMake(0, 0, width, height);
if (width > kMaxResolution || height > kMaxResolution) {
CGFloat ratio = width/height;
if (ratio > 1) {
bounds.size.width = kMaxResolution;
bounds.size.height = roundf(bounds.size.width / ratio);
}
else {
bounds.size.height = kMaxResolution;
bounds.size.width = roundf(bounds.size.height * ratio);
}
}
CGFloat scaleRatio = bounds.size.width / width;
CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
CGFloat boundHeight;
UIImageOrientation orient = image.imageOrientation;
switch(orient) {
case UIImageOrientationUp: //EXIF = 1
transform = CGAffineTransformIdentity;
break;
case UIImageOrientationUpMirrored: //EXIF = 2
transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
transform = CGAffineTransformScale(transform, -1.0, 1.0);
break;
case UIImageOrientationDown: //EXIF = 3
transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
transform = CGAffineTransformRotate(transform, M_PI);
break;
case UIImageOrientationDownMirrored: //EXIF = 4
transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
transform = CGAffineTransformScale(transform, 1.0, -1.0);
break;
case UIImageOrientationLeftMirrored: //EXIF = 5
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
transform = CGAffineTransformScale(transform, -1.0, 1.0);
transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
break;
case UIImageOrientationLeft: //EXIF = 6
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
break;
case UIImageOrientationRightMirrored: //EXIF = 7
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeScale(-1.0, 1.0);
transform = CGAffineTransformRotate(transform, M_PI / 2.0);
break;
case UIImageOrientationRight: //EXIF = 8
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
transform = CGAffineTransformRotate(transform, M_PI / 2.0);
break;
default:
[NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];
}
UIGraphicsBeginImageContext(bounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
CGContextScaleCTM(context, -scaleRatio, scaleRatio);
CGContextTranslateCTM(context, -height, 0);
}
else {
CGContextScaleCTM(context, scaleRatio, -scaleRatio);
CGContextTranslateCTM(context, 0, -height);
}
CGContextConcatCTM(context, transform);
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageCopy;
}
因为上传阿里云的时候,上传的图片命名不能相同,所以利用了随机数,和时间戳相结合的命名方法。
随机数方法:
//随机数+ (NSString*)getTransactionID { NSDate* date = [NSDate date]; NSMutableString* strDate = [NSMutableString stringWithFormat:@"%@", date]; NSString *s1=[strDate stringByReplacingOccurrencesOfString:@"-" withString:@""]; NSString *s2= [s1 stringByReplacingOccurrencesOfString:@" " withString:@""]; NSString *s3= [s2 stringByReplacingOccurrencesOfString:@":" withString:@""]; int n = (arc4random() % 9000) + 1000; NSMutableString* transactionID = [NSMutableString stringWithString:[s3 substringToIndex:14]]; [transactionID appendString:[NSString stringWithFormat:@"%d", n]]; [transactionID stringByReplacingOccurrencesOfString:@" " withString:@""]; return transactionID; }
时间戳方法:
//获取当前时间戳 +(NSString *)getNowTimeTimestamp{ NSDate* dat = [NSDate dateWithTimeIntervalSinceNow:0]; NSTimeInterval a=[dat timeIntervalSince1970]; NSString*timeString = [NSString stringWithFormat:@"%0.f", a];//转为字符型 return timeString; }
三.在调用相册的地方引用方法
[AliyunUpload uploadImage:headImageArray FileDirectory:ENT_fileItemImageBody success:^(NSString *obj) { _pictureStr =obj ;//就是上传后图片名 dispatch_sync(dispatch_get_main_queue(), ^{ }); }];
拿到图片名后需要拼接字符串@“http://yijiao.oss-cn-qingdao.aliyuncs.com/”,即可是网络图片。
自己写了个小demo,需要的可以下载,如有什么疑问,可以评论提出。
注: 本篇独发金蝶云社区。
推荐阅读