iOS 表單格式上傳 OSS

前言

最近的工做是負責寫埋點 SDK,學到了不少知識,不單單是 iOS 方面的,還包括 JavaScriptNodeJS大數據等方面的一些知識,有時間會把本身學到的知識所有記錄下來,一則是加深印象,二是若是剛好遇到有須要的人,但願能提供一些思路。html

1.爲何要用表單格式上傳 OSS

爲何要用表單格式上傳數據到 OSS,你們知道,若是借用 AliyunOSSiOS 的話,會很是 easy 且輕鬆搞定 OSS 數據上傳,那麼爲何非要拼接成表單格式上傳到 OSS 呢?ios

這就和具體需求有關了。git

咱們的需求是,爲公司的幾個 APP 作埋點 SDK,考慮到這幾個 APP 都有可能使用 AliyunOSSiOS,那麼爲了不衝突,兼容自己已集成 AliyunOSSiOS 的 APP,咱們的埋點 SDK 就不能再集成 AliyunOSSiOS 了,因而就選擇了表單格式上傳。github

2.核心代碼及思路

2.1 先調用服務端接口獲取簽名
[NNNetworking requestWithURL:@"獲取簽名的接口" params:@{@"key":@"value"} success:^(id  _Nullable responseObject) {
    if (responseObject) {
        NSDictionary *origDict = responseObject;
        NSString *statusCode = origDict[@"statusCode"];
        if ([statusCode isEqualToString:@"200"]) {
            NSDictionary *resultDict = origDict[@"result"];
            NSString *policy = resultDict[@"policy"];
            NSString *OSSAccessKeyId = resultDict[@"OSSAccessKeyId"];
            NSString *signature = resultDict[@"signature"];
            NSString *key = resultDict[@"dirPath"];
            
            NSMutableDictionary *parameterDict = [[NSMutableDictionary alloc]init];
            [parameterDict setValue:OSSAccessKeyId forKey:@"OSSAccessKeyId"];
            [parameterDict setValue:policy            forKey:@"policy"];
            [parameterDict setValue:signature         forKey:@"signature"];
            [parameterDict setValue:key forKey:@"key"];
            // 上傳數據到 OSS
            [NNNetworking uploadOSSWithParameter:parameterDict uploadDataArray:@[] success:^(id  _Nonnull obj) {
                
            } fail:^(NSError * _Nonnull error) {
                
            }];
        }
    }
} failure:^(NSError * _Nullable error) {
    
}];
複製代碼

因爲本身作的自己就是 SDK,因此強制不能使用第三方框架,好比經常使用的網絡框架 AFNetworking 或 Alamofire 都不能使用。bash

2.2 接着拼接簽名、策略、key 等字段,拼接成表單結構,而後上傳至 OSS
+ (void)uploadOSSWithParameter:(NSDictionary *)parameterDict uploadDataArray:(NSArray *)dataArray success:(void (^)(id obj))success fail:(void (^)(NSError *error))fail {
    // 分界線的標識符
    NSString *TWITTERFON_FORM_BOUNDARY = @"IaX0GHJdM5gRIXY_S37dFzTjrYcygaI4lr8JjgHY_hUURrbjP8LbpzJ7KEQ2AbcY5yU3Jc";
    // 根據 url 初始化 request
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://桶名.oss-cn-beijing.aliyuncs.com"] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10];
    // 分界線
    NSString *MPboundary = [[NSString alloc]initWithFormat:@"--%@",TWITTERFON_FORM_BOUNDARY];
    // 結束符
    NSString *endMPboundary=[[NSString alloc]initWithFormat:@"%@--",MPboundary];
    
    // http body 的字符串
    NSMutableString *body = [[NSMutableString alloc] init];
    
    // 參數的集合的全部key的集合
    NSArray *keys= [parameterDict allKeys];
    // 遍歷keys
    for(int i = 0; i < [keys count]; i++) {
        // 獲得當前key
        NSString *key=[keys objectAtIndex:i];
        // 添加分界線,換行
        [body appendFormat:@"%@\r\n",MPboundary];
        // 添加字段名稱,換2行
        [body appendFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",key];
        // 添加字段的值
        [body appendFormat:@"%@\r\n",[parameterDict objectForKey:key]];
    }
    // 添加分界線,換行
    [body appendFormat:@"%@\r\n",MPboundary];
    // 聲明pic字段,文件名爲boris.png
    [body appendFormat:@"%@", [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"file\"; filename=\"%@\"\r\n",@"MyFilename"]];
    // 聲明上傳文件的格式
    [body appendFormat:@"Content-Type: image/png\r\n\r\n"];
    NSString *paraString = [dataArray componentsJoinedByString:@","];
    
    NSString *end=[[NSString alloc]initWithFormat:@"\r\n%@",endMPboundary];
    
    // 聲明myRequestData,用來放入http body
    NSMutableData *myRequestData = [NSMutableData data];
    // 將body字符串轉化爲UTF8格式的二進制
    [myRequestData appendData:[body dataUsingEncoding:NSUTF8StringEncoding]];
    // data加入
    [myRequestData appendData:[paraString dataUsingEncoding:NSUTF8StringEncoding]];
    // 加入結束符--AaB03x--
    [myRequestData appendData:[end dataUsingEncoding:NSUTF8StringEncoding]];
    
    // 設置HTTPHeader中Content-Type的值
    NSString *content = [[NSString alloc]initWithFormat:@"multipart/form-data; boundary=%@",TWITTERFON_FORM_BOUNDARY];
    [request setValue:content forHTTPHeaderField:@"Content-Type"];
    // 設置Content-Length
    [request setValue:[NSString stringWithFormat:@"%d", (int)[myRequestData length]] forHTTPHeaderField:@"Content-Length"];
    
    // 設置http body
    [request setHTTPBody:myRequestData];
    // http method
    [request setHTTPMethod:@"POST"];
    // 鏈接(NSURLSession)
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            
        } else {
            if (success) {
                success(@"");
            }
        }
        NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"body:%@", str);
    }];
    [dataTask resume];
}
複製代碼

參考文檔:

相關文章
相關標籤/搜索