Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## Change Log

### v0.3.0

- Add support for OSS Callback

### v0.2.0

- Add aliyun/sts
Expand Down
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,35 @@ Object的common prefix,包含在`list_objects`的结果中。
Common prefix让用户不需要遍历所有的object(可能数量巨大)而找出前缀,
在模拟目录结构时非常有用。

## 上传回调

在`put_object`和`resumable_upload`时可以指定一个`Callback`,这样在文件
成功上传到OSS之后,OSS会向用户提供的服务器地址发起一个HTTP POST请求,
以通知用户相应的事件发生了。用户可以在收到这个通知之后进行相应的动作,
例如更新数据库、统计行为等。更多有关上传回调的内容请参考[OSS上传回调][oss-callback]。

下面的例子将演示如何使用上传回调:

callback = Aliyun::OSS::Callback.new(
url: 'http://10.101.168.94:1234/callback',
query: {user: 'put_object'},
body: 'bucket=${bucket}&object=${object}'
)

begin
bucket.put_object('files/hello', callback: callback)
rescue Aliyun::OSS::CallbackError => e
puts "Callback failed: #{e.message}"
end

**注意**

1. callback的url**不能**包含query string,而应该在`:query`参数中指定
2. 可能出现文件上传成功,但是执行回调失败的情况,此时client会抛出
`CallbackError`,用户如果要忽略此错误,需要显示接住这个异常。
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

显示 => 显式

3. 详细的例子可以参考[callback.rb](examples/aliyun/oss/callback.rb)
4. 接受回调的server可以参考[callback_server.rb](rails/aliyun_oss_callback_server.rb)

## 断点上传/下载

OSS支持大文件的存储,用户如果上传/下载大文件(Object)的时候中断了(网络
Expand Down Expand Up @@ -386,3 +415,4 @@ SDK采用rspec进行测试,如果要对SDK进行修改,请确保没有break
[custom-domain]: https://help.aliyun.com/document_detail/oss/user_guide/oss_concept/oss_cname.html
[aliyun-sts]: https://help.aliyun.com/document_detail/ram/intro/concepts.html
[sdk-api]: http://www.rubydoc.info/gems/aliyun-sdk/
[oss-callback]: https://help.aliyun.com/document_detail/oss/user_guide/upload_object/upload_callback.html
1 change: 1 addition & 0 deletions aliyun-sdk.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'rspec', '~> 3.3'
spec.add_development_dependency 'webmock', '~> 1.22'
spec.add_development_dependency 'simplecov', '~> 0.10'
spec.add_development_dependency 'minitest', '~> 5.8'

spec.required_ruby_version = '>= 1.9.3'
end
61 changes: 61 additions & 0 deletions examples/aliyun/oss/callback.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# -*- encoding: utf-8 -*-

$LOAD_PATH.unshift(File.expand_path("../../../../lib", __FILE__))
require 'yaml'
require 'json'
require 'aliyun/oss'

##
# 用户在上传文件时可以指定“上传回调”,这样在文件上传成功后OSS会向用户
# 提供的服务器地址发起一个HTTP POST请求,相当于一个异步的通知机制。用
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个通知机制不是异步的,而是同步的。

# 户可以在收到回调的时候做相应的动作。
# 1. 如何接受OSS的回调可以参考代码目录下的
# rails/aliyun_oss_callback_server.rb
# 2. 只有put_object和resumable_upload支持上传回调

# 初始化OSS client
Aliyun::Common::Logging.set_log_level(Logger::DEBUG)
conf_file = '~/.oss.yml'
conf = YAML.load(File.read(File.expand_path(conf_file)))
bucket = Aliyun::OSS::Client.new(
:endpoint => conf['endpoint'],
:cname => conf['cname'],
:access_key_id => conf['access_key_id'],
:access_key_secret => conf['access_key_secret']).get_bucket(conf['bucket'])

# 辅助打印函数
def demo(msg)
puts "######### #{msg} ########"
puts
yield
puts "-------------------------"
puts
end

demo "put object with callback" do
callback = Aliyun::OSS::Callback.new(
url: 'http://10.101.168.94:1234/callback',
query: {user: 'put_object'},
body: 'bucket=${bucket}&object=${object}'
)

begin
bucket.put_object('files/hello', callback: callback)
rescue Aliyun::OSS::CallbackError => e
puts "Callback failed: #{e.message}"
end
end

demo "resumable upload with callback" do
callback = Aliyun::OSS::Callback.new(
url: 'http://10.101.168.94:1234/callback',
query: {user: 'resumable_upload'},
body: 'bucket=${bucket}&object=${object}'
)

begin
bucket.resumable_upload('files/world', '/tmp/x', callback: callback)
rescue Aliyun::OSS::CallbackError => e
puts "Callback failed: #{e.message}"
end
end
34 changes: 33 additions & 1 deletion lib/aliyun/oss/bucket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ def list_objects(opts = {})
# @option opts [Hash] :metas 设置object的meta,这是一些用户自定
# 义的属性,它们会和object一起存储,在{#get_object}的时候会
# 返回这些meta。属性的key不区分大小写。例如:{ 'year' => '2015' }
# @option opts [Callback] :callback 指定操作成功后OSS的
# 上传回调,上传成功后OSS会向用户的应用服务器发一个HTTP POST请
# 求,`:callback`参数指定这个请求的相关参数
# @yield [HTTP::StreamWriter] 如果调用的时候传递了block,则写入
# 到object的数据由block指定
# @example 流式上传数据
Expand All @@ -188,7 +191,20 @@ def list_objects(opts = {})
# @example 指定Content-Type和metas
# put_object('x', :file => '/tmp/x', :content_type => 'text/html',
# :metas => {'year' => '2015', 'people' => 'mary'})
# @note 如果opts中指定了:file,则block会被忽略
# @example 指定Callback
# callback = Aliyun::OSS::Callback.new(
# url: 'http://10.101.168.94:1234/callback',
# query: {user: 'put_object'},
# body: 'bucket=${bucket}&object=${object}'
# )
#
# bucket.put_object('files/hello', callback: callback)
# @raise [CallbackError] 如果文件上传成功而Callback调用失败,抛
# 出此错误
# @note 如果opts中指定了`:file`,则block会被忽略
# @note 如果指定了`:callback`,则可能文件上传成功,但是callback
# 执行失败,此时会抛出{OSS::CallbackError},用户可以选择接住这
# 个异常,以忽略Callback调用错误
def put_object(key, opts = {}, &block)
args = opts.dup

Expand Down Expand Up @@ -420,15 +436,31 @@ def get_object_cors(key)
# 果设置为true,则在上传的过程中不会写checkpoint文件,这意味着
# 上传失败后不能断点续传,而只能重新上传整个文件。如果这个值为
# true,则:cpt_file会被忽略。
# @option opts [Callback] :callback 指定文件上传成功后OSS的
# 上传回调,上传成功后OSS会向用户的应用服务器发一个HTTP POST请
# 求,`:callback`参数指定这个请求的相关参数
# @yield [Float] 如果调用的时候传递了block,则会将上传进度交由
# block处理,进度值是一个0-1之间的小数
# @raise [CheckpointBrokenError] 如果cpt文件被损坏,则抛出此错误
# @raise [FileInconsistentError] 如果指定的文件与cpt中记录的不一
# 致,则抛出此错误
# @raise [CallbackError] 如果文件上传成功而Callback调用失败,抛
# 出此错误
# @example
# bucket.resumable_upload('my-object', '/tmp/x') do |p|
# puts "Progress: #{(p * 100).round(2)} %"
# end
# @example 指定Callback
# callback = Aliyun::OSS::Callback.new(
# url: 'http://10.101.168.94:1234/callback',
# query: {user: 'put_object'},
# body: 'bucket=${bucket}&object=${object}'
# )
#
# bucket.resumable_upload('files/hello', '/tmp/x', callback: callback)
# @note 如果指定了`:callback`,则可能文件上传成功,但是callback
# 执行失败,此时会抛出{OSS::CallbackError},用户可以选择接住这
# 个异常,以忽略Callback调用错误
def resumable_upload(key, file, opts = {}, &block)
args = opts.dup

Expand Down
3 changes: 3 additions & 0 deletions lib/aliyun/oss/exception.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ def get_request_id(response)

end # ServerError

class CallbackError < ServerError
end # CallbackError

##
# ClientError represents client exceptions caused mostly by
# invalid parameters.
Expand Down
2 changes: 1 addition & 1 deletion lib/aliyun/oss/http.rb
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ def do_request(verb, resources = {}, http_options = {}, &block)
logger.debug("Received HTTP response, code: #{r.code}, headers: " \
"#{r.headers}, body: #{r.body}")

[r.headers, r.body]
r
end

def get_user_agent
Expand Down
Loading