IOS 将多张图片上传至阿里云服务器原创
金蝶云社区-honey缘木鱼
honey缘木鱼
7人赞赏了该文章 501次浏览 未经作者许可,禁止转载编辑于2019年02月22日 19:28:57

这段时间一直写关于小程序和Vue.js的文章,却忽略了自己的本职工作:IOS开发,听到IOS开发,貌似已经被这些容易上手的web端代替,但是,原生就是原生,它的页面流畅度及用户体验效果还是比较好的。在此,记录下用IOS 上传多张图片到阿里云的功能封装。


一.准备工作

    1. 去阿里云网站下载SDK及官网demo

     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,需要的可以下载,如有什么疑问,可以评论提出。



注: 本篇独发金蝶云社区。

赞 7