You need to enable JavaScript to run this app.
文档中心
火山引擎入门实验

火山引擎入门实验

复制全文
下载 pdf
存储
使用 ETag 验证简单上传场景下 TOS 对象的完整性
复制全文
下载 pdf
使用 ETag 验证简单上传场景下 TOS 对象的完整性

本文介绍使用 ETag 验证简单上传对象完整性的过程。

前言

使用TOS进行数据上传或下载的过程中,可能会因为公网传输过程中在TOS外部的网络劫持、数据缓存等原因,导致数据不一致等问题。TOS提供了多种数据一致性相关的特性,您可以利用这些特性确保数据上传或下载的一致性。在TOS场景中,数据一致性校验分为上传对象一致性校验以及下载对象一致性校验,。

本实验介绍使用Etag验证简单上传场景下的数据完整性。

关于实验
  • 预计部署时间:30分钟
  • 级别:初级
  • 相关产品:TOS
  • 受众: 通用
实验说明
  • 点击此链接登录控制台。

  • 如果您还没有账户,请点击此链接注册账户。

实验步骤

一、完整性效验原理

将对象上传到TOS时,它们可以作为单个对象上传,也可以通过分片进行上传。

当对象使用简单上传时,该对象的 Etag 即为整个对象的MD5摘要,根据上传完成后响应的Etag跟本地文件的Etag进行对比即可;对于已经上传完成,后续要对其进行完整性效验的场景,可以使用HeadObject来获取对象Etag,然后进行对比。

当对象使用分片上传时,该对象的 ETag 不是整个对象的 MD5 摘要。TOS 会在上传时计算每个分片的 MD5 摘要。MD5 摘要用于确定最终对象的 ETag。TOS 将 MD5 摘要的字节串联在一起,然后计算这些串联值的 MD5 摘要。创建 ETag 的最后一步为在末尾添加一个短横线和分片总数。

示例,考虑使用 ETag 为 C9A5A6878D97B48CC965C1E41859F034-14 的分片上传的对象上传。在本例中,C9A5A6878D97B48CC965C1E41859F034 是串联在一起的所有摘要的 MD5 摘要。-14 表示有 14 个分片与此对象的分片上传相关联。

您可以使用 GetObject 或 HeadObject 操作并指定与单个分片对齐的分片编号或字节范围,来获取单个分片的校验和。借助此方法,您可以使用该校验和验证单个分片,而无需等待所有分片都上传完毕后再验证数据完整性。使用此方法时,还可以仅请求未通过完整性测试的单个分片。

由于 TOS计算分片对象的校验和的方式,复制对象时,对象的校验和值可能会发生变化。如果您使用的是SDK 或 REST API,并且调用 CopyObject,TOS可以复制大小不超过 CopyObject API 操作限制的任何对象。无论对象是在单个请求中上传还是作为分片上传的一部分上传,TOS都可以作为单个操作执行此复制。使用 copy 命令,对象的校验和是完整对象的直接校验和。如果对象最初是使用分片上传进行上传的,那么即使数据没有变化,校验和值也会发生变化。

二、代码实现

package main

import (
	"context"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"github.com/volcengine/ve-tos-golang-sdk/v2/tos"
	"io/ioutil"
	"os"
	"strings"
)

func log(msg string) {
	fmt.Println(msg + "\n")
}

// 获取文件的 md5
func Md5Value(bytes []byte) (md5s string) {
	h := md5.New()
	h.Write(bytes)
	md5s = hex.EncodeToString(h.Sum(nil))
	return
}

// 获取文件的 md5 值
func GetFileMd5Hash(fileBytes []byte) string {
	hash := Md5Value(fileBytes)
	log(fmt.Sprintf("get file hash: %v", hash))
	return hash
}

func main() {

	// 先计算文件的MD5
	fileName := "test"
	
	path := fmt.Sprintf("/Users/xxxx/%s", fileName)
	
	localfile, err := os.Open(path)
	
	if err != nil {
		panic(err)
	}
	defer localfile.Close()
	
	all, err := ioutil.ReadAll(localfile)

	localMD5Values := GetFileMd5Hash(all)

	// 上传对象并获取返回的Etag
	var (
		accessKey = "xxxxx"
		secretKey = "xxxxx"
		endpoint  = "tos-cn-beijing.volces.com"
		region    = "cn-beijing"
	)

	client, errClient := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey)))

	if errClient != nil {
		panic(err)
	}

	file, _ := os.Open("/Users/xxxx/test")

	inputstruct := tos.PutObjectBasicInput{
		Bucket: "xxxx",
		Key:    "xxxx",
	}

	get, err := client.PutObjectV2(context.Background(), &tos.PutObjectV2Input{
		inputstruct,
		file,
	})

	if err != nil {
		fmt.Println(err)
	}

	EtagValue := strings.Trim(get.ETag, "\"")

	fmt.Println(EtagValue)

	if EtagValue == localMD5Values {
		fmt.Println("效验成功")
	} else {
		fmt.Println("效验失败")
		// 效验失败可以添加失败处理逻辑
	}

}

参考文档:
[1] TOS Go SDK

最近更新时间:2024.01.03 11:00:03
这个页面对您有帮助吗?
有用
有用
无用
无用