OSS 移动端SDK 上传文件的方式可以分为:简单上传,追加上传,和断点续传。

简单上传

上传Object可以直接上传OSSData,或者通过NSURL上传一个文件:

OSSPutObjectRequest * put = [OSSPutObjectRequest new];
// 必填字段
put.bucketName = @"<bucketName>";
put.objectKey = @"<objectKey>";
put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];
// put.uploadingData = <NSData *>; // 直接上传NSData
// 可选字段,可不设置
put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
    // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度
    NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
};
// 以下可选字段的含义参考: https://docs.aliyun.com/#/pub/oss/api-reference/object&PutObject
// put.contentType = @"";
// put.contentMd5 = @"";
// put.contentEncoding = @"";
// put.contentDisposition = @"";
// put.objectMeta = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"value1", @"x-oss-meta-name1", nil]; // 可以在上传时设置元信息或者其他HTTP头部
OSSTask * putTask = [client putObject:put];
[putTask continueWithBlock:^id(OSSTask *task) {
    if (!task.error) {
        NSLog(@"upload object success!");
    } else {
        NSLog(@"upload object failed, error: %@" , task.error);
    }
    return nil;
}];
// [putTask waitUntilFinished];
// [put cancel];

上传到文件目录

OSS服务是没有文件夹这个概念的,所有元素都是以文件来存储,但给用户提供了创建模拟文件夹的方式。创建模拟文件夹本质上来说是创建了一个名字以“/”结尾的文件,对于这个文件照样可以上传下载,只是控制台会对以“/”结尾的文件以文件夹的方式展示。

如,在上传文件是,如果把ObjectKey写为"folder/subfolder/file",即是模拟了把文件上传到folder/subfolder/下的file文件。注意,路径默认是”根目录”,不需要以’/‘开头。

上传时设置Content-Type和开启校验MD5

上传时可以显式指定ContentType,如果没有指定,SDK会根据文件名或者上传的ObjectKey自动判断。另外,上传Object时如果设置了Content-Md5,那么OSS会用之检查消息内容是否与发送时一致。SDK提供了方便的Base64和MD5计算方法。

OSSPutObjectRequest * put = [OSSPutObjectRequest new];
// 必填字段
put.bucketName = @"<bucketName>";
put.objectKey = @"<objectKey>";
put.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];
// put.uploadingData = <NSData *>; // 直接上传NSData
// 设置Content-Type,可选
put.contentType = @"application/octet-stream";
// 设置MD5校验,可选
put.contentMd5 = [OSSUtil base64Md5ForFilePath:@"<filePath>"]; // 如果是文件路径
// put.contentMd5 = [OSSUtil base64Md5ForData:<NSData *>]; // 如果是二进制数据
// 进度设置,可选
put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
    // 当前上传段长度、当前已经上传总长度、一共需要上传的总长度
    NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
};
OSSTask * putTask = [client putObject:put];
[putTask continueWithBlock:^id(OSSTask *task) {
    if (!task.error) {
        NSLog(@"upload object success!");
    } else {
        NSLog(@"upload object failed, error: %@" , task.error);
    }
    return nil;
}];
// [putTask waitUntilFinished];
// [put cancel];

追加上传

Append Object以追加写的方式上传文件。通过Append Object操作创建的Object类型为Appendable Object,而通过Put Object上传的Object是Normal Object。

OSSAppendObjectRequest * append = [OSSAppendObjectRequest new];
// 必填字段
append.bucketName = @"<bucketName>";
append.objectKey = @"<objectKey>";
append.appendPosition = 0; // 指定从何处进行追加
NSString * docDir = [self getDocumentDirectory];
append.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];
// 可选字段
append.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
    NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
};
// 以下可选字段的含义参考:https://docs.aliyun.com/#/pub/oss/api-reference/object&AppendObject
// append.contentType = @"";
// append.contentMd5 = @"";
// append.contentEncoding = @"";
// append.contentDisposition = @"";
OSSTask * appendTask = [client appendObject:append];
[appendTask continueWithBlock:^id(OSSTask *task) {
    NSLog(@"objectKey: %@", append.objectKey);
    if (!task.error) {
        NSLog(@"append object success!");
        OSSAppendObjectResult * result = task.result;
        NSString * etag = result.eTag;
        long nextPosition = result.xOssNextAppendPosition;
    } else {
        NSLog(@"append object failed, error: %@" , task.error);
    }
    return nil;
}];

上传后回调通知

客户端在上传Object时可以指定OSS服务端在处理完上传请求后,通知您的业务服务器,在该服务器确认接收了该回调后将回调的结果返回给客户端。因为加入了回调请求和响应的过程,相比简单上传,使用回调通知机制一般会导致客户端花费更多的等待时间。

具体说明参考:Callback

代码示例:

OSSPutObjectRequest * request = [OSSPutObjectRequest new];
request.bucketName = @"<bucketName>";
request.objectKey = @"<objectKey>";
request.uploadingFileURL = [NSURL fileURLWithPath:@<filepath>"];
// 设置回调参数
request.callbackParam = @{
                          @"callbackUrl": @"<your server callback address>",
                          @"callbackBody": @"<your callback body>"
                          };
// 设置自定义变量
request.callbackVar = @{
                        @"<var1>": @"<value1>",
                        @"<var2>": @"<value2>"
                        };
request.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
    NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
};
OSSTask * task = [client putObject:request];
[task continueWithBlock:^id(OSSTask *task) {
    if (task.error) {
        OSSLogError(@"%@", task.error);
    } else {
        OSSPutObjectResult * result = task.result;
        NSLog(@"Result - requestId: %@, headerFields: %@, servercallback: %@",
              result.requestId,
              result.httpResponseHeaderFields,
              result.serverReturnJsonString);
    }
    return nil;
}];

数据完整性校验

因为移动端网络环境的复杂性,OSS SDK提供了基于MD5和CRC64的端到端的数据完整性验证功能。

  • MD5校验

    需要在上传文件时提供文件的Content-MD5值,OSS服务器会帮助用户进行MD5校验,只有在OSS服务器计算接收到的文件得到的MD5值和上传提供的MD5一致时才可以上传成功,从而保证上传数据的完整性。

    OSSPutObjectRequest * request = [OSSPutObjectRequest new];
    request.bucketName = BUCKET_NAME;
    ...
    request.contentMd5 = [OSSUtil fileMD5String:filepath];
    
  • CRC校验

    与MD5相比,CRC64可以同时上传并计算CRC值。

    // 构造上传请求
    OSSPutObjectRequest * request = [OSSPutObjectRequest new];
    request.bucketName = OSS_BUCKET_PRIVATE;
    ///....
    request.crcFlag = OSSRequestCRCOpen;
    // 开启crc效验后。如果在传输中数据不一致,会提示OSSClientErrorCodeInvalidCRC 错误。
    OSSTask * task = [_client putObject:request];
    [[task continueWithBlock:^id(OSSTask *task) {
        //如果crc效验失败,会有error
        XCTAssertNil(task.error);
        return nil;
    }] waitUntilFinished];