更新时间:2025-08-15 GMT+08:00
分享

上传回调(Go SDK)

功能说明

用户可以在上传对象请求中设置回调参数,OBS在对象上传成功之后,将上传结果回调特定服务器,并将回调结果返回给用户。

回调成功,返回回调结果给客户端,同时将上传对象的Etag以头域返回,当回调结果也包含Etag时,将对Etag拼接后返回。

回调失败,返回203,表示对象上传成功但是回调失败。

接口约束

  • 您必须是桶拥有者或拥有上传对象的权限,才能上传对象。建议使用IAM或桶策略进行授权,如果使用IAM则需授予obs:object:PutObject权限,如果使用桶策略则需授予PutObject权限。相关授权方式介绍可参见OBS权限控制概述,配置方式详见使用IAM自定义策略配置对象策略
  • OBS支持的Region与Endpoint的对应关系,详细信息请参见地区与终端节点
  • 如果上传的图片大小超过25M,则无法通过imageInfo相关魔法变量获取图片基本信息,会导致回调失败。
  • 上传回调需要使用SDK接口拓展配置,指定WithCallbackHeader方法,该方法目前仅支持流式上传、文件上传和断点续传接口。

方法定义

WithCallbackHeader(callback string)

请求参数说明

表1 请求参数列表

参数名称

参数类型

是否必选

描述

calllback

string

必选

参数解释

上传回调策略。

约束限制:

该字段为经过BASE64编码的JSON字符串,该JSON字符串中携带的回调参数参考表2 回调参数

默认取值:

表2 回调参数

参数名称

参数类型

是否必选

描述

callbackUrl

string

必选

参数解释

对象上传成功之后,OBS向此url发送回调请求,请求方法为POST。

约束限制:

  • callbackUrl需要做url编码。例如:“http://www.example.com/中文?key=中文名”需要编码成“http://www.example.com/%E4%B8%AD%E6%96%87?key=%E4%B8%AD%E6%96%87%E5%90%8D”。
  • 支持设置多个url,以英文分号(;)分隔,最多支持10个。

默认取值:

callbackHost

string

可选

参数解释

发起回调请求的Host头域的值。

默认取值:

无,会使用callbackUrl解析出来的Host。

callbackBody

string

必选

参数解释

发起回调请求的body体。

约束限制:

  • body体格式必须符合callbackBodyType中设置的媒体类型。
  • 回调body体支持系统变量,系统变量如表3所示。例如:key=$(key)&hash=$(etag),其中变量key、etag是系统变量。如果用户上传的对象是图片,可以在参数中设置imageInfo.width和imageInfo.height表示该图片的宽高。例如:key=$(key)&hash=$(etag)&w=$(imageInfo.width)&h=$(imageInfo.height)。

默认取值:

callbackBodyType

string

可选

参数解释

发起回调请求的Content-Type头域的值。

取值范围:

  • application/x-www-form-urlencoded
  • application/json

默认取值:

application/json

表3 表3 回调body体支持的系统变量

变量名称

参数类型

描述

fname

string

上传的原始文件名。

fsize

string

文件的大小,单位为字节。

名称兼容size。

etag

string

对象的ETag。

bucket

string

上传的对象所属桶名。

key

string

参数解释:

上传对象的名字。对象名是对象在存储桶中的唯一标识。对象名是对象在桶中的完整路径,路径中不包含桶名。

例如,您对象的访问地址为examplebucket.obs.cn-north-4.ap-southeast-1.myhuaweicloud.com/folder/test.txt 中,对象名为folder/test.txt。

取值范围:

长度大于0且不超过1024的字符串。

默认取值:

ext

string

上传文件的后缀名,通过自动检测的mimeType或者$(fname)的后缀来获取。

名称兼容mimeType。

override

string

上传对象是否产生覆盖,值只会是true或false。

上传对象的对象名在桶中已存在,即会产生覆盖,override为true,否则为false。当桶开启多版本时,不会产生覆盖写,override始终为false。

imageInfo

string

获取所上传图片的基本信息。只支持上传图片的场景。

该变量包含$(imageInfo.width)和$(imageInfo.height)两个子字段,分别表示图片的宽度和高度。

说明:

如果上传的图片大小超过25M,则无法通过imageInfo相关魔法变量获取图片基本信息,会导致回调失败。

返回结果说明

返回结果参考原有方法函数调用,参考代码示例

该返回参数会新增两个方法:

1. ReadCallbackBody: 调用该函数,可以读取回调服务端的返回体。

2. CloseCallbackBody: 关闭回调服务端的返回体,该方法必须调用。

代码示例

本示例用于流式上传到examplebucket桶中的example/objectname,并指定上传回调服务器为http://example.com:80

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// 引入依赖包
import (
     "fmt"
     "bytes"
     "encoding/base64"
     "encoding/json"
     "strings"
     obs "github.com/huaweicloud/huaweicloud-sdk-go-obs/obs"
)

func main() {
    //推荐通过环境变量获取AKSK,这里也可以使用其他外部引入方式传入,如果使用硬编码可能会存在泄露风险。
    //您可以登录访问管理控制台获取访问密钥AK/SK,获取方式请参见https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html。
    ak := os.Getenv("AccessKeyID")
    sk := os.Getenv("SecretAccessKey")
    // 【可选】如果使用临时AK/SK和SecurityToken访问OBS,同样建议您尽量避免使用硬编码,以降低信息泄露风险。您可以通过环境变量获取访问密钥AK/SK,也可以使用其他外部引入方式传入。
    // securityToken := os.Getenv("SecurityToken")
    // endpoint填写Bucket对应的Endpoint, 这里以华北-北京四为例,其他地区请按实际情况填写。
    endPoint := "https://obs.cn-north-4.myhuaweicloud.com"
    // 创建obsClient实例
    // 如果使用临时AKSK和SecurityToken访问OBS,需要在创建实例时通过obs.WithSecurityToken方法指定securityToken值。
    obsClient, err := obs.New(ak, sk, endPoint/*, obs.WithSecurityToken(securityToken)*/)

    input := &obs.PutObjectInput{}
    input.Bucket = "bucketname"
    input.Key = "objectname"
    input.Body = strings.NewReader("Hello OBS")
    callbackMap := map[string]string{}
    callbackMap["callbackUrl"] = "http://example.com:80"
    // callbackMap["callbackHost"] = "example.com"
    callbackMap["callbackBody"] = "filename=${object}&size=${size}&mimeType=${mimeType}"
    // callbackMap["callbackBodyType"] = "application/x-www-form-urlencoded"
    callbackBuffer := bytes.NewBuffer([]byte{})
    callbackEncoder := json.NewEncoder(callbackBuffer)
    callbackEncoder.SetEscapeHTML(false)
    err := callbackEncoder.Encode(callbackMap)
    if err != nil {
        fmt.Print(err)
        return
    }
    callbackVal := base64.StdEncoding.EncodeToString(callbackBuffer.Bytes())
    output, err := obsClient.PutObject(input, obs.WithCallbackHeader(callbackVal))
    if err == nil {
        // 必须调用该方法
        defer output.CloseCallbackBody()
        fmt.Printf("RequestId:%s\n", output.RequestId)
        fmt.Printf("ETag:%s\n", output.ETag)
        p := make([]byte, 1024)
        var readErr error
        var readCount int
        // 读取回调内容
        for {
            readCount, readErr = output.ReadCallbackBody(p)
            if readCount > 0 {
                fmt.Printf("%s", p[:readCount])
            }
            if readErr != nil {
                break
            }
        }
    } else if obsError, ok := err.(obs.ObsError); ok {
        fmt.Printf("Code:%s\n", obsError.Code)
        fmt.Printf("Message:%s\n", obsError.Message)
    }
}

相关链接

  • 上传对象过程中返回的错误码含义、问题原因及处理措施可参考OBS错误码
  • 上传对象常见问题请参见上传对象失败
  • 回调功能更多介绍参考OBS回调

相关文档