本文主要介绍上传回调中的常见错误及分析处理。
如果您想查看上传回调中常见错误及原因,请查看常见错误及原因。如果您想查看上传回调的介绍及使用请参考以下内容。
OSS在文件上传完成时,可以提供回调(Callback)给您的回调服务器(Callback Server)。在上传请求中携带相应的回调参数,即能实现上传回调。支持上传回调的API接口有PutObject、PostObject、CompleteMultipartUpload。更详细的介绍请参见开发指南中的上传回调和Callback API。
说明:本文中的回调服务器(Callback Server)有时也叫业务服务器。
OSS上传回调的流程如下。
上图OSS上传回调的流程解释说明如下所示。
数据流 | 含义 | 说明 |
---|---|---|
1 | 上传文件并携带回调参数。详细格式请参见PostObject。 | 通过SDK调用API接口(PutObject、CompleteMultipartUpload、PostObject)完成。 |
2 | OSS存储文件后发起回调。 | OSS向上传请求中指定的CallbackUrl发起POST请求,回调超时时间是5秒。超时时间为固定值,不支持配置。回调请求POST的格式请参见发起回调请求。 |
3 | 回调服务器返回处理结果。 |
|
4 | OSS返回上传、回调结果。 |
|
上传回调时可以通过设置回调参数,例如:回调服务器URL、发送给回调服务器的数据、格式等,上传回调参数如下所示。且回调服务器处理回调时,需要一些上下文信息,例如bucket
、object
等通过系统变量指定,而系统变量以外的上下文信息,可以通过自定义变量指定。
字段 | 含义 | 说明 |
---|---|---|
callbackUrl | 回调服务器URL | 必选参数 |
callbackHost | 回调请求消息头中Host 的值 |
可选参数,默认为callbackUrl |
callbackBody | 回调请求的消息体 | 必选参数,内容可以包括系统变量和自定义变量 |
callbackBodyType | 回调请求消息头中Content-Type 的值,即callbackBody 的数据格式 |
可选参数,支持application/x-www-form-urlencoded 和application/json ,默认为前者 |
通过上传请求携带上传回调参数有两种实现方式:
x-oss-callback
,携带回调参数。这种方式比较常用,推荐该方式。callback
,携带回调参数。x-oss-callback
或callback
的值生成规则如下。
Callback := Base64(CallbackJson) CallbackJson := '{' CallbackUrlItem, CallbackBodyItem [, CallbackHostItem, CallbackBodyTypeItem] '}' CallbackUrlItem := '"'callbackUrl'"' ':' '"'CallbackUrlValue'"' CallbackBodyItem := '"'callbackBody'"' ':' '"'CallbackBodyValue'"' CallbackHostItem := '"'callbackHost'"' ':' '"'CallbackHostValue'"' CallbackBodyTypeItem := '"'callbackBodyType'"' : '"'CallbackBodyType'"' CallbackBodyType := application/x-www-form-urlencoded | application/json
CallbackJson
值的示例如下。
{ "callbackUrl" : "http://abc.com/test.php", "callbackHost" : "oss-cn-hangzhou.aliyuncs.com", "callbackBody" : "{\"bucket\":${mimeType}, \"object\":${object},\"size\":${size},\"mimeType\":${mimeType},\"my_var\":${x:my_var}}", "callbackBodyType" : "application/json" }
或
{ "callbackUrl" : "http://abc.com/test.php", "callbackBody" : "bucket=${bucket}&object=${object}&etag=${etag}&size=${size}&mimeType=${mimeType}&my_var=${x:my_var}" }
CallbackJson
示例中的callbackBody
包括如${bucket}
、${object}
、${size}
的变量,即为OSS定义的系统变量,OSS回调时会用实际值替换系统变量。OSS定义的系统变量如下表所示。
变量 | 含义 |
${bucket} | 存储空间名称 |
${object} | 文件名称 |
${etag} | 文件的ETag |
${size} | 文件大小 |
${mimeType} | 文件类型,如image、jpeg等 |
${imageInfo.height} | 图片高度 |
${imageInfo.width} | 图片宽度 |
${imageInfo.format} | 图片格式,如jpg、png等 |
说明:
- 系统变量大小写敏感。
- 系统变量的格式为
${bucket}
。- imageInfo针对于图片格式,非图片格式值为空。
CallbackJson
示例中的callbackBody
包括如${x:my_var}
的变量,即自定义变量,OSS回调时会用自定义的值替换掉自定义变量。自定义变量的值可以在上传请求中定义并携带,有以下两种方式。
x-oss-callback-var
,携带自定义变量。这种方式比较常用,也是推荐方式。callback-var
,携带自定义变量。x-oss-callback-var
或callback-var
的生成规则如下。
CallbackVar := Base64(CallbackVarJson) CallbackVarJson := '{' CallbackVarItem [, CallbackVarItem]* '}' CallbackVarItem := '"''x:'VarName'"' : '"'VarValue'"'
CallbackVarJson
值的示例如下。
{ "x:my_var1" : "value1", "x:my_var2" : "value2" }
注意:
- 自定义变量必须以x:开头,区分大小写,格式为
${x:my_var}
。- 自定义变量的长度受消息头、URL的长度限制,建议自定义变量不超过10个,总长度不超过512Byte。
回调服务器(Callback Server),是一个HTTP服务器,处理OSS发送的回调请求,POST消息。回调服务器的URL即上传回调参数中的callbackUrl
。回调服务器是用户自己实现的处理逻辑,实现上传数据的记录、审查、处理、统计等。
注意: OSS的回调服务器示例中提供了签名校验的实现,推荐直接使用该部分代码。
语言 | 示例 | 运行方法 |
---|---|---|
Java | AppCallbackServer.zip | 解压后执行java -jar oss-callback-server-demo.jar 9000 。 |
PHP | callback-php-demo.zip | Apache环境下部署运行。 |
Python | callback_app_server.py.zip | 解压后执行python callback_app_server.py 。 |
Ruby | oss-callback-server | 执行ruby server.rb 。 |
部分SDK对上述步骤进行了封装,如Java、JS,部分SDK需要使用上面的规则生成上传回调参数和自定义变量,如Python、PHP、C。SDK的使用示例如下。
SDK | 上传回调示例 | 说明 |
---|---|---|
Java | CallbackSample.java | 注意CallbackBody 中的转义字符。 |
Python | object_callback.py | - |
PHP | Callback.php | 上传的$options中OSS_CALLBACK 和OSS_CALLBACK_VAR 不需要base64,SDK会处理。 |
C# | UploadCallbackSample.cs | 使用using读取PutObjectResult.ResponseStream ,但要确保关闭PutObjectResult.ResponseStream 。 |
JS | object.test.js | - |
C | oss_callback_sample.c | - |
Ruby | callback.rb | - |
iOS | <var1> 的格式为x:var1 。 |
|
Andriod | 注意CallbackBody 中的转义字符。 |
注意:Go SDK暂不支持上传回调。
PostObject支持上传回调,回调参数通过表单域callback
携带,自定义变量通过独立的表单域携带,详情请参见PostObjet。
SDK | 上传回调示例 |
---|---|
Java | PostObjectSample.java |
Python | object_post.py |
JS | JavaScript客户端签名直传 |
C# | PostPolicySample.cs |
上传回调的调试分为两部分:上传的客户端、处理回调的回调服务器。建议先调试客户端上传部分,再调试回调服务器部分。两部分单独调试完成后,再运行完整的上传回调。
http://oss-demo.aliyuncs.com:23450
,即回调参数callbackUrl
。该回调服务器只验证回调请求的签名,对回调请求不做处理。对于签名验证成功的回调请求,返回{"Status":"OK"}
;签名验证失败的回调请求,返回400 Bad Request
,非POST请求返回501 Unsupported method
。示例回调服务器的代码请参见callback_app_server.py.zip。语言 | 示例 | 运行方法 |
---|---|---|
Java | AppCallbackServer.zip | 解压后执行java -jar oss-callback-server-demo.jar 9000 。 |
PHP | callback-php-demo.zip | Apache环境下部署运行。 |
Python | callback_app_server.py.zip | 解压后执行python callback_app_server.py 。 |
C# | callback-server-dotnet.zip | 编译后执行aliyun-oss-net-callback-server.exe 127.0.0.1 80 。 |
Go | callback-server-go.zip | 编译后执行aliyun_oss_callback_server 。 |
Ruby | oss-callback-server | 执行ruby aliyun_oss_callback_server.rb 。 |
回调服务器可以通过curl命令调试,常用的命令如下所示。
# 向回调服务器发送消息体为`object=test_obj`的`POST`请求,可以使用以下命令 curl -d "object=test_obj" http://oss-demo.aliyuncs.com:23450 -v # 向回调服务器发送消息体为文件`post.txt`内容的`POST`请求,可以使用以下命令 curl -d @post.txt http://oss-demo.aliyuncs.com:23450 -v # 向回调服务器发送消息体为文件`post.txt`内容的`POST`请求,并携带指定的消息头`Content-Type` curl -d @post.txt -H "Content-Type: application/json" http://oss-demo.aliyuncs.com:23450 -v
说明:
- 调试回调服务器时,可以先忽略签名验证部分,因为
CURL
模拟签名功能比较困难。- 签名验证功能OSS示例中已经提供,建议直接使用。
- 回调服务器建议有日志功能,记录收到的所有消息,方便调试、跟踪。
- 回调服务器正确处理回调请求后,一定要返回200,而不是其它的
20x
。- 回调服务器返回给OSS的消息体,一定要是Json格式,
Content-Type
设置为application/json
。
回调参数设置错误,或参数格式错误。常见的错误是ArgumentValue之间的回调参数,不是有效Json格式。在Json中\"
是转义字符,如"callbackBody":"{"bucket":${bucket},"object":${object}}"
应该为"callbackBody":"{\"bucket\":${bucket},\"object\":${object}}"
。针对具体的SDK,请参见对应的上传回调示例,详情请参考SDK使用示例部分。
<Error> <Code>InvalidArgument</Code> <Message>The callback configuration is not json format.</Message> <RequestId>587C79A3DD373E2676F73ECE</RequestId> <HostId>bucket.oss-cn-hangzhou.aliyuncs.com</HostId> <ArgumentName>callback</ArgumentName> <ArgumentValue>{"callbackUrl":"8.8.8.8:9090","callbackBody":"{"bucket":${bucket},"object":${object}}","callbackBodyType":"application/json"}</ArgumentValue> </Error>
转义后的字符 | 转义前的字符 |
---|---|
\\ | \\\\ |
\" | \\\” |
\b | \\b |
\f | \\f |
\n | \\n |
\r | \\r |
\t | \\t |
报错信息 | 问题原因 | 解决方法 |
---|---|---|
<Error> <Code>CallbackFailed</Code> <Message>Response body is not valid json format.</Message> <RequestId>587C81A125F797621829923D</RequestId> <HostId>bucket.oss-cn-hangzhou.aliyuncs.com</HostId> </Error> |
回调服务器返回给OSS的消息体非Json格式。 | 您可以通过 |
<Error> <Code>CallbackFailed</Code> <Message>Error status : -1.OSS can not connect to your callbackUrl, please check it.</Message> <RequestId>587C8735355BE8694A8E9100</RequestId> <HostId>bucket.oss-cn-hangzhou.aliyuncs.com</HostId> </Error> |
回调服务器处理时间超过5秒,OSS认为超时。 | 建议回调服务器的处理逻辑修改为异步,保证在5秒内处理完毕并返回结果给OSS。 |
<Error> <Code>CallbackFailed</Code> <Message>Error status : -1 8.8.8.8:9090 reply timeout, cost:5000ms, timeout:5000ms (err -4, errno115)</Message> <RequestId>587C8D382AE0B92FA3EEF62C</RequestId> <HostId>bucket.oss-cn-hangzhou.aliyuncs.com</HostId> </Error> |
回调服务器处理时间超过5秒,OSS认为超时。 | - |
<Error> <Code>CallbackFailed</Code> <Message>Error status : 400.</Message> <RequestId>587C89A02AE0B92FA3C7981D</RequestId> <HostId>bucket.oss-cn-hangzhou.aliyuncs.com</HostId> </Error> |
回调服务器返回给OSS的消息的状态码是400 。 |
请检查回调服务器的处理逻辑。 |
<Error> <Code>CallbackFailed</Code> <Message>Error status : 502.</Message> <RequestId>587C8D382AE0B92FA3EEF62C</RequestId> <HostId>bucket.oss-cn-hangzhou.aliyuncs.com</HostId> </Error> |
回调服务器未启动,或者缺少上传回调参数中的CallbackUrl ,或者OSS与回调服务器的网络不通。 |
推荐在ECS上部署回调服务器,与OSS同属内网可以节省流量费用,同时保证网络质量。 |
错误原因有以下两种情况。
说明:上图中
ef bb bf
这三个字节就是bom头。应用服务器返回OSS响应时,请去掉bom头。
此类错误较多,例如502、400等,示例如下。
注意:
- 400或者其他的status比如404/403等是指应用服务器返回给OSS的HTTP status是400或者404/403等,正常情况下应用服务器必须返回200给OSS。
- 502是由于应用服务器根本就没有开启Web服务,没有监听OSS发过来的回调请求。
出于安全考虑,OSS的回调请求只会等待5秒。如果5秒后还没有返回,那么OSS就会主动断开与应用服务器的连接,并返回给客户端超时错误,错误信息中的IP可以忽略。