iOS SDK 提供了数据完整性校验来保证您在上传、下载过程中数据的安全性。

上传文件的数据完整性校验

由于移动端网络环境的复杂性,数据在客户端和服务器之间传输时有可能会出错。OSS iOS 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];

下载文件的数据完整性校验

iOS SDK 在下载过程中提供了基于 CRC 的端到端的数据完整性效验功能。

在读取下载数据流时,如果开启了 CRC 效验,会在读取完数据流自动验证数据完整性。

以下代码用于开启 CRC 校验:

OSSGetObjectRequest * request = [OSSGetObjectRequest new];
request.bucketName = ...;
//开启crc效验
request.crcFlag = OSSRequestCRCOpen;

OSSTask * task = [testProxyClient getObject:request];

[[task continueWithBlock:^id(OSSTask *task) {
	//如果开启了crc效验,并有在传输中有数据错误的情况。会提示OSSClientErrorCodeInvalidCRC的错误
    XCTAssertNil(task.error);
    return nil;
}] waitUntilFinished];

注:如果设置onReceiveData block。开启CRC效验后,需要自行比较CRC数值是否一致。范例如下
OSSGetObjectRequest * request = [OSSGetObjectRequest new];
request.bucketName = ....
request.crcFlag = OSSRequestCRCOpen;
....
    
__block uint64_t localCrc64 = 0;
	//如果设置onReceiveData block
NSMutableData *receivedData = [NSMutableData data];
request.onRecieveData = ^(NSData *data) {
	if (data)
	{
		NSMutableData *mutableData = [data mutableCopy];
    	void *bytes = mutableData.mutableBytes;
    	localCrc64 = [OSSUtil crc64ecma:localCrc64 buffer:bytes length:data.length];
    	[receivedData appendData:data];
    }
};
    
__block uint64_t remoteCrc64 = 0;
OSSTask * task = [_client getObject:request];
[[task continueWithBlock:^id(OSSTask *task) {
	XCTAssertNil(task.error);
   	OSSGetObjectResult *result = task.result;
    if (result.remoteCRC64ecma) 
	{
    	NSScanner *scanner = [NSScanner scannerWithString:result.remoteCRC64ecma];
		[scanner scanUnsignedLongLong:&remoteCrc64];
        if (remoteCrc64 == localCrc64)
        {
        	NSLog(@"crc64校验成功!");
        }
		else
        {
        	NSLog(@"crc64校验失败!");
        }
   }
   return nil;
}] waitUntilFinished];