在OSS中,操作的基本数据单元是文件(Object)。OSS Ruby SDK提供了丰富的文件上传方式。

上传本地文件

通过Bucket#put_object接口,并指定:file参数来上传一个本地文件到OSS:

require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  endpoint: 'endpoint',
  access_key_id: 'AccessKeyId', access_key_secret: 'AccessKeySecret')

bucket = client.get_bucket('my-bucket')
bucket.put_object('my-object', :file => 'local-file')
			

流式上传

如果要上传的文件太大,或者一次性上传耗时太长,您可以通过流式上传的方式,一次处理部分内容,直到完成整个文件的上传。

通过Bucket#put_object接口,并指定block参数将流式生成的内容上传到OSS:

require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  endpoint: 'endpoint',
  access_key_id: 'AccessKeyId', access_key_secret: 'AccessKeySecret')

bucket = client.get_bucket('my-bucket')
bucket.put_object('my-object') do |stream|
  100.times { |i| stream << i.to_s }
end
			

断点续传上传

断点续传上传将要上传的文件分成若干个分片(Part)分别上传,所有分片都上传完成后,将所有分片合并成完整的文件,完成整个文件的上传。

通过Bucket#resumable_upload接口实现断点续传上传,包含以下参数:

  • key上传到OSS的Object名字。
  • file待上传的本地文件路径。
  • opts可选项,主要包括:
    • :cpt_file指定checkpoint文件的路径。如果不指定,则默认是本地文件同目录下的file.cpt,其中file是本地文件的名字。
    • :disable_cpt如果指定为true,则上传过程中不会记录上传进度,上传失败后也无法进行续传。
    • :part_size指定每个分片的大小,默认为4MB。
    • &block如果调用时传递了block,则上传进度会由block来处理。
详细的参数说明请参考API文档
说明 如果上传过程中某一分片上传失败,再次上传时会从 checkpoint文件中记录的点继续上传。再次调用 Bucket#resumable_upload时需指定与上次相同的checkpoint文件。文件上传完成后,checkpoint文件将被删除。

以下代码用于断点续传上传:

require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  endpoint: 'endpoint',
  access_key_id: 'AccessKeyId', access_key_secret: 'AccessKeySecret')

bucket = client.get_bucket('my-bucket')
bucket.resumable_upload('my-object', 'local-file') do |p|
  puts "Progress: #{p}"
end

bucket.resumable_upload(
  'my-object', 'local-file',
  :part_size => 100 * 1024, :cpt_file => '/tmp/x.cpt') { |p|
  puts "Progress: #{p}"
}
			
说明
  • SDK会将上传的中间状态信息记录在cpt文件中,用户需确保对cpt文件有写权限。
  • cpt文件不仅记录了上传的中间状态信息,还附带校验功能。cpt文件不允许编辑。如果cpt文件损坏则无法继续上传,整个文件上传完成后cpt文件会被删除。
  • 上传过程中如果本地文件发生了改变,会导致上传失败。

追加上传

通过Bucket#append_object来上传可追加的文件。调用该接口时需要指定文件追加的position,首次追加操作的position必须为0,后续追加操作的position是Object的当前大小。

  • 文件不存在时,调用append_object会创建一个可追加的文件。
  • 文件存在时,调用append_object会向文件末尾追加内容。
require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  endpoint: 'endpoint',
  access_key_id: 'AccessKeyId', access_key_secret: 'AccessKeySecret')

bucket = client.get_bucket('my-bucket')
# 创建可追加的文件
bucket.append_object('my-object', 0) {}

# 向文件末尾追加内容
next_pos = bucket.append_object('my-object', 0) do |stream|
  100.times { |i| stream << i.to_s }
end
next_pos = bucket.append_object('my-object', next_pos, :file => 'local-file-1')
next_pos = bucket.append_object('my-object', next_pos, :file => 'local-file-2')
			
说明
  • 只能向Appendable类型的Object追加内容。
  • 不支持对Appendable类型的Object进行拷贝。

上传回调

用户在上传文件时可以指定上传回调。文件上传成功后,OSS会向用户提供的服务器地址发起HTTP POST请求,用户可以在收到回调时执行相应的操作。更多有关上传回调的内容,请参考 OSS 上传回调
说明 目前OSS支持上传回调的接口只有 put_objectresumable_upload。有关上传回调的详细示例,请参考callback.rb

使用put_object上传文件时指定了上传回调,并将此次上传的Bucket和Object信息添加在body中。如果应用服务器收到这个回调,则表明文件已成功上传到OSS了。

require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  endpoint: 'endpoint',
  access_key_id: 'AccessKeyId', access_key_secret: 'AccessKeySecret')

bucket = client.get_bucket('my-bucket')

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', file: '/tmp/x', callback: callback)
rescue Aliyun::OSS::CallbackError => e
  puts "Callback failed: #{e.message}"
end
			

resumable_upload的调用方法与put_object类似。

require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  endpoint: 'endpoint',
  access_key_id: 'AccessKeyId', access_key_secret: 'AccessKeySecret')

bucket = client.get_bucket('my-bucket')

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

begin
  bucket.resumable_upload('files/hello', '/tmp/x', callback: callback)
rescue Aliyun::OSS::CallbackError => e
  puts "Callback failed: #{e.message}"
end
			
说明
  • callback的url不能包含query string,须在:query参数中指定。
  • 如果出现文件上传成功,但是执行回调失败时,client会抛出 CallbackError。用户如果忽略此错误,需要显式接住这个异常。
  • 接收回调的server请参考callback_server.rb