上传回调(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)
请求参数说明
参数名称 |
参数类型 |
是否必选 |
描述 |
---|---|---|---|
calllback |
string |
必选 |
参数解释: 上传回调策略。 约束限制: 该字段为经过BASE64编码的JSON字符串,该JSON字符串中携带的回调参数参考表2 回调参数。 默认取值: 无 |
参数名称 |
参数类型 |
是否必选 |
描述 |
---|---|---|---|
callbackUrl |
string |
必选 |
参数解释: 对象上传成功之后,OBS向此url发送回调请求,请求方法为POST。 约束限制:
默认取值: 无 |
callbackHost |
string |
可选 |
参数解释: 发起回调请求的Host头域的值。 默认取值: 无,会使用callbackUrl解析出来的Host。 |
callbackBody |
string |
必选 |
参数解释: 发起回调请求的body体。 约束限制:
默认取值: 无 |
callbackBodyType |
string |
可选 |
参数解释: 发起回调请求的Content-Type头域的值。 取值范围:
默认取值: application/json |
变量名称 |
参数类型 |
描述 |
---|---|---|
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) } } |