OBS 对象上传下载的一致性校验
1 方案概述
1.1 背景说明
OBS服务在提供各种对象上传下载等服务时,已经为用户提供了安全、高可靠的数据存储能力,为确保传输和应用过程中可能产生的数据一致性问题,OBS服务也为用户提供了各种方式来校验对象的MD5一致性,本文就几中常用的方式进行介绍。
1.2 方案说明
OBS服务为用户提供了不同工具/SDK使用场景下基于MD5校验数据一致性能力:
其中OBS Browser和obsutil工具,在开启MD5校验功能后,进行对象上传时,只有在OBS服务端上已上传对象的MD5值与本地对象MD5值一致时才可以上传成功,从而保证上传数据的一致性,同时也将MD5值存放在了对象元数据中。在开启MD5校验功能后进行对象下载时,OBS服务端会将存放在对象元数据中的MD5值与下载后的对象MD5值进行比对,只有两者一致才能成功下载对象。如图1所示。
图1 OBS Browser和obsutil进行对象上传下载MD5校验流程
另一种方法是OBS SDK,它提供接口参数,利用content-MD5头域能力提供上传数据一致性校验。上传对象完成校验后,对象元数据中的etag值等同于MD5值,但当对象为多段对象或加密对象时,对象元数据中的etag值不是MD5值。在这种情况,MD5没有对比值,OBS SDK也无法对下载对象操作进行MD5校验,但用户可在上传对象时将MD5值存入对象自定义元数据中,供下载对象时进行MD5校验,这部分内容在3.3中会详细讲到。
2 对象上传的校验操作指导
2.1 方式一:OBS Browser
步骤一:登录OBS Browser后,单击页面右上角的“系统配置”图标,在“系统配置>基本配置”窗口,勾选“启用MD5校验”并保存设置,如图2所示。
图2 OBS Browser配置MD5校验
步骤二:选择需要上传的对象,单击“确定”后,在页面右上角单击“任务管理”图标,在“正在运行”任务管理列表页签中查看对象上传状态和MD5校验状态,待对象上传完成,可以在“已完成”任务管理列表页签中查看到MD5校验结果,如图3所示。
图3 OBS Browser查看MD5校验结果
说明:
· 开启MD5校验会影响上传下载性能。
· OBS Browser工具如何使用和下载,请参考对象存储服务OBS帮助文档(链接:https://support.huaweicloud.cn/obs/index.html)。
2.2 方式二:obsutil
使用obsutil工具时,可通过附加-vmd5参数来上传对象,此时OBS服务端会帮用户进行MD5校验,只有在OBS服务端上已上传对象的MD5值与本地对象MD5值一致时才可以上传成功,如图4所示。
图4 obsutil查看MD5校验结果
说明:
· 开启MD5校验会影响上传下载性能。
· obsutil工具如何使用和下载,请参考对象存储服务OBS帮助文档(链接:https://support.huaweicloud.cn/obs/index.html)。
2.3 方式三:OBS SDK
除了上述两种方法,您还可以基于华为云SDK,通过编写代码调用华为云API来校验对象上传的一致性。如果不匹配则上传失败,返回HTTP 400错误(Error Message: The Content-MD5 you specified did not match what we received.)
华为云有10种语言SDK可供选择,下面列举其中2种语言MD5校验。
2.3.1 OBS Java SDK
您可以通过ObsClient.base64Md5来直接计算Content-MD5头域,并使用ObjectMetadata.setContentMd5来设置对象MD5值。OBS服务端会将该Content-MD5头域与对象数据计算出的经过Base64编码后MD5值进行对比,示例代码如下。
String endPoint = "https://your-endpoint";
String ak = "*** Provide your Access Key ***";
String sk = "*** Provide your Secret Key ***";
// 创建ObsClient实例
ObsClient obsClient = new ObsClient(ak, sk, endPoint);
// 计算并设置MD5值
ObjectMetadata metadata = new ObjectMetadata();
File file = new File("E:\\README.txt");
FileInputStream fis = new FileInputStream(file);
InputStream is = (InputStream)fis;
String contentMd5 = obsClient.base64Md5(is);
metadata.setContentMd5(contentMd5);
// 带MD5校验功能上传文件
obsClient.putObject("bucketname", "objectkey", file, metadata);
说明:
· 开启MD5校验会影响上传下载性能。
· OBS SDK各工具如何使用和下载,请参考对象存储服务OBS帮助文档(链接:https://developer.huaweicloud.cn/sdk?OBS)。
2.3.2 OBS Python SDK
您可以通过PutObjectHeader.md5来设置对象Content-MD5头域。其中GetFileMd5函数用于计算对象的MD5值(用户可以自定义,仅供参考),示例代码如下。
# 引入模块
from obs import ObsClient
# 创建ObsClient实例
obsClient = ObsClient(
access_key_id='*** Provide your Access Key ***',
secret_access_key='*** Provide your Secret Key ***',
server='https://your-endpoint'
)
from obs import PutObjectHeader
headers = PutObjectHeader()
# 计算MD5
def GetFileMd5(filename):
if not os.path.isfile(filename):
return
myhash = hashlib.md5()
f = open(filename, 'rb')
str = f.read()
myhash.update(str)
f.close()
return myhash.digest()
# 带MD5校验上传文件
filename = ‘E:\\README.txt’
contentMd5 = GetFileMd5(filename)
contentMd5B64 = base64.b64encode(contentMd5).decode()
headers.md5 = contentMd5B64
resp = obsClient.putFile('bucketname', 'objectkey', filename, headers=headers)
if resp.status < 300:
print('requestId:', resp.requestId)
else:
print('errorCode:', resp.errorCode)
print('errorMessage:', resp.errorMessage)
说明:
· 开启MD5校验会影响上传下载性能。
· OBS SDK各工具如何使用和下载,请参考对象存储服务OBS帮助文档(链接:https://developer.huaweicloud.cn/sdk?OBS)。
3 对象下载的校验操作指导
3.1 方式一:OBS Browser
步骤一:登录OBS Browser后,单击页面右上角的“系统配置”图标,在“系统配置>基本配置”窗口,勾选“启用MD5校验”并保存设置,如图5所示。
图5 OBS Browser配置MD5校验
步骤二:选择需要下载的文件,单击“确定”后,在页面右上角单击“任务管理”图标,在“正在运行”任务管理列表页签中可以查看对象下载状态和MD5校验状态,待对象下载完成,可以在“已完成”任务管理列表页签中查看到MD5校验结果,如图6所示。
图6 OBS Browser查看MD5校验结果
说明:
· OBS Browser工具如果在上传对象时未开启MD5校验的功能,那在下载对象时即使开启了MD5校验功能其实也没有进行MD5校验。
3.2 方式二:obsutil
使用obsutil工具时,若通过附加-vmd5参数来上传对象 ,此时OBS服务端会帮用户进行MD5校验,同时还会把此MD5值存放在该对象的元数据中(如图7所示),以便于下载的时候读取该MD5值,与下载对象计算的MD5值进行比较,如图8所示。
图7 存放在对象元数据中的MD5值
图8 使用obsutil附加-vmd5参数来下载对象
说明:
· OBS Browser工具如果在上传对象时未开启MD5校验的功能,那在下载对象时即使开启了MD5校验功能其实也没有进行MD5校验。
3.3 方式三:OBS SDK
OBS服务SDK对上传对象的Content-MD5头域进行一致性校验,但未做下载对象的一致性校验,但可以通过在上传对象时把MD5值存放到对象自定义元数据里,对象下载后,将此自定义元数据里的MD5值与下载到本地的对象进行校验比对。
华为云有10种语言SDK可供选择,下面列举其中2种。
3.3.1 OBS Java SDK
在上传对象时通过ObjectMetadata.addUserMetadata来存放对象Content-MD5头域值。对象下载后,将此自定义元数据里的MD5校验值和下载到本地文件的MD5校验值进行对比,示例代码如下。
String endPoint = "https://your-endpoint";
String ak = "*** Provide your Access Key ***";
String sk = "*** Provide your Secret Key ***";
// 创建ObsClient实例
ObsClient obsClient = new ObsClient(ak, sk, endPoint);
// 把Content-MD5头域值存放入对象自定义元数据中
ObjectMetadata metadata = new ObjectMetadata();
File file = new File("E:\\README.txt");
FileInputStream fis = new FileInputStream(file);
InputStream is = (InputStream)fis;
String contentMd5 = obsClient.base64Md5(is);
metadata.addUserMetadata("property1", contentMd5);
// 上传文件
obsClient.putObject("bucketname", "objectkey", file, metadata);
// 获取对象的自定义元数据
ObjectMetadata metadataDown = obsClient.getObjectMetadata("bucketname", "objectkey");
String contentMd5Origin = metadataDown.getUserMetadata("property1");
// 对下载后的对象进行MD5值进行比对
ObsObject obsObject = obsClient.getObject("chongchongbucket001", "cc.txt");
String contentMd5Download = obsClient.base64Md5(obsObject.getObjectContent());
if(contentMd5Origin.contentEquals(contentMd5Download))
System.out.println("Object MD5 validation passes!\n");
else
System.out.println("Object MD5 validation failed!\n");
3.3.2 OBS Python SDK
在上传对象时通过metadata参数来存放对象Content-MD5头域值。对象下载后,将此自定义元数据里的Content-MD5头域值与下载到本地的对象进行校验比对,示例代码如下。
# 引入模块
from obs import ObsClient
# 创建ObsClient实例
obsClient = ObsClient(
access_key_id='*** Provide your Access Key ***',
secret_access_key='*** Provide your Secret Key ***',
server='https://your-endpoint'
)
from obs import PutObjectHeader
headers = PutObjectHeader()
# MD5值计算函数
def GetFileMd5(filename):
if not os.path.isfile(filename):
return
myhash = hashlib.md5()
f = open(filename, 'rb')
str = f.read()
myhash.update(str)
f.close()
return myhash.digest()
# 把MD5值存放入对象自定义元数据中
filename = ‘E:\\README.txt’
contentMd5 = GetFileMd5(filename)
contentMd5B64 = base64.b64encode(contentMd5).decode()
metadata = {'property1' : 'contentMd5B64'}
resp = obsClient.putFile('bucketname', 'objectkey', filename, metadata=metadata)
if resp.status < 300:
print('requestId:', resp.requestId)
else:
print('errorCode:', resp.errorCode)
print('errorMessage:', resp.errorMessage)
# 获取对象自定义元数据中的MD5值
resp = obsClient.putFile('bucketname', 'objectkey')
contentMd5Origin = dict(resp.header).get('property1')
if resp.status < 300:
print('requestId:', resp.requestId)
else:
print('errorCode:', resp.errorCode)
print('errorMessage:', resp.errorMessage)
# 对下载后的对象进行MD5值进行比对
filenameDown = "E:\\README_DOWN.txt"
resp = obsClient.putFile('bucketname', 'objectkey', downloadPath=filenameDown)
contentMd5Download = base64.b64encode(GetFileMd5(filenameDown)).decode()
if (contentMd5Origin == contentMd5Download):
print("Object MD5 validation passes!\n")
else:
print("Object MD5 validation failed!\n")
- 点赞
- 收藏
- 关注作者
评论(0)