全部产品
Search
文档中心

对象存储 OSS:Go数据校验

更新时间:Dec 20, 2023

OSS提供基于MD5和CRC64的数据校验,确保上传、下载和拷贝文件(Object)过程中的数据完整性。

注意事项

  • 本文以华东1(杭州)外网Endpoint为例。如果您希望通过与OSS同地域的其他阿里云产品访问OSS,请使用内网Endpoint。关于OSS支持的Region与Endpoint的对应关系,请参见访问域名和数据中心

  • 本文以从环境变量读取访问凭证为例。如何配置访问凭证,请参见配置访问凭证

  • 本文以OSS域名新建OSSClient为例。如果您希望通过自定义域名、STS等方式新建OSSClient,请参见初始化

MD5校验

如果上传文件时设置了Content-MD5,OSS会根据接收的内容计算MD5。OSS计算的MD5值和上传提供的MD5值不一致时,则返回InvalidDigest异常,从而保证数据的完整性。返回InvalidDigest异常后,您需要重新上传文件。

上传文件时进行MD5校验:

package main

import (
    "crypto/md5"
    "encoding/base64"
    "fmt"
    "os"
    "strings"

    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func main() {
    // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
    provider, err := oss.NewEnvironmentVariableCredentialsProvider()
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 创建OSSClient实例。
    // yourEndpoint填写Bucket对应的Endpoint,以华东1(杭州)为例,填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。
    client, err := oss.New("yourEndpoint", "", "", oss.SetCredentialsProvider(&provider))
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // yourBucketName填写存储空间名称。
    bucket, err := client.Bucket("yourBucketName")
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 获取文件内容。
    content := "yourObjectValue"

    // 计算md5值。
    h := md5.New()
    h.Write([]byte(content))
    strMd5 := base64.StdEncoding.EncodeToString(h.Sum(nil))

    // 简单上传。
    err = bucket.PutObject("yourObjectName", strings.NewReader(content), oss.ContentMD5(strMd5))
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
}
说明

putObject、getObject、appendObject、postObject、uploadPart支持MD5校验。

CRC64校验

上传、下载和拷贝文件时默认开启CRC数据校验,以确保数据的完整性。

使用CRC64校验,有如下注意事项:

  • putObject、getObject、appendObject、uploadPart支持CRC64校验。上传时默认开启CRC校验,如果客户端计算的CRC值与服务端返回的CRC值不一致,则会返回错误。

  • 范围下载不支持CRC64校验。

  • CRC64校验会占用一定的CPU,对上传、下载速度均会有影响。

以下代码用于追加上传文件时进行CRC64数据完整性校验:

package main

import (
    "fmt"
    "os"
    "strings"

    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func main() {
    // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
    provider, err := oss.NewEnvironmentVariableCredentialsProvider()
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 创建OSSClient实例。
    // yourEndpoint填写Bucket对应的Endpoint,以华东1(杭州)为例,填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。
    client, err := oss.New("yourEndpoint", "", "", oss.SetCredentialsProvider(&provider))
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // yourBucketName填写存储空间名称。
    bucket, err := client.Bucket("yourBucketName")
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 第一次追加的位置是0,返回值为下一次追加的位置。后续追加的位置是追加前文件的长度。
    // yourObjectName填写不包含Bucket名称在内的Object的完整路径。
    request := &oss.AppendObjectRequest{
        ObjectKey: "yourObjectName",
        Reader:    strings.NewReader("YourObjectAppendValue1"),
        Position:  0,
    }

    // 第一次追加时,初始化crc的值为0。
    options := []oss.Option{oss.InitCRC(0)}
    result, err := bucket.DoAppendObject(request, options)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 第二次追加的位置从第一次的返回长度开始。
    request = &oss.AppendObjectRequest{
        ObjectKey: "yourObjectName",
        Reader:    strings.NewReader("YourObjectAppendValue2"),
        Position:  result.NextPosition,
    }

    // 第二次追加的初始化crc值为第一次返回值。
    options = []oss.Option{oss.InitCRC(result.CRC)}
    result, err = bucket.DoAppendObject(request, options)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    // 您可以进行多次AppendObject操作。
}