使用Ruby SDK将文件上传到Amazon S3

9

我正在尝试上传一个文件,一个简单的hello.txt。我按照文档操作,但是无法将它上传到我的存储桶中。

#  START AWS CLIENT

s3 = Aws::S3::Resource.new
bucket = s3.bucket(BUCKET_NAME)

begin

  s3.buckets[BUCKET_NAME].objects[KEY].write(:file => FILE_NAME)
  puts "Uploading file #{FILE_NAME} to bucket #{BUCKET_NAME}."

  bucket.objects.each do |obj|
    puts "#{obj.key} => #{obj.etag}"
  end

rescue Aws::S3::Errors::ServiceError
  # rescues all errors returned by Amazon Simple Storage Service
end

我正在遵循http://docs.aws.amazon.com/AmazonS3/latest/dev/UploadObjSingleOpRuby.html。 出现的错误信息如下:

➜ s3-tester ruby main.rb /Users/.rvm/gems/ruby-2.1.1/gems/aws-sdk-resources-2.0.34/lib/aws-sdk-resources/collection.rb:79:in 'method_missing: undefined method []' for '<Aws::Resources::Collection:0x000001031e5100> (NoMethodError)' from 'main.rb:18:in <main>'

请注意,本文中的HTML标签已保留。

我收到一个“a[]没有方法”的错误。 - R.J. Robinson
把错误放在问题里。 - Arup Rakshit
4个回答

16

主要问题是您安装了AWS SDK的2.x版本,但是您参考的文档是1.x版本的。可以在此处找到2.x版本的文档:

http://docs.aws.amazon.com/sdkforruby/api/index.html

要更新示例以使用2.x版本,请执行以下操作:

s3 = Aws::S3::Resource.new
bucket = s3.bucket(BUCKET_NAME)

begin

  bucket.object(KEY).upload_file(FILENAME)
  puts "Uploading file #{FILE_NAME} to bucket #{BUCKET_NAME}."

  bucket.objects.each do |obj|
    puts "#{obj.key} => #{obj.etag}"
  end

rescue Aws::S3::Errors::ServiceError
    # rescues all errors returned by Amazon Simple Storage Service
end

主要差异:

  • 版本1使用#[]方法在集合中通过键引用对象。版本2有两种方法,#objects()#object(key)。后者是getter,前者列举桶中的所有对象。
  • 版本2有一个专门的#upload_file方法,用于管理从磁盘上传对象。这类似于版本1中的#write,但它还可以使用多个线程并行上传大型对象部分。

5
我使用了以下脚本,如果不存在,则创建一个新的存储桶(bucket),然后将所选文件上传到其中。
#!/usr/bin/env ruby
#

require 'rubygems'
require 'aws-sdk'

bucket_name = ARGV[0]
file_name = ARGV[1]


# Get an instance of the S3 interface.
s3 = Aws::S3::Client.new(region: 'us-east-1')

key = File.basename(file_name)
resp = s3.list_buckets()
buckets = resp.data.buckets

if buckets.select { |b| b.name == bucket_name }.length == 0
  puts 'creating bucket'
  s3.create_bucket(bucket: bucket_name)
end

puts "Uploading file #{file_name} to bucket #{bucket_name}..."

# Upload a file.
s3.put_object(
  :bucket => bucket_name,
  :key    => key,
  :body   => IO.read(file_name)
)

如果你将这些保存到upload.rb,你就可以通过运行以下命令将simple.txt上传到my_bucket: $ ruby upload.rb my_bucket simple.txt

2
client = Aws::S3::Client.new(region: 'us-east-1')
resource = Aws::S3::Resource.new(client: client)
bucket = resource.bucket(BUCKET_NAME)
begin
  # s3.buckets[BUCKET_NAME].objects[KEY].write(:file => FILE_NAME)
  # puts "Uploading file #{FILE_NAME} to bucket #{BUCKET_NAME}."

  bucket.objects.each do |o|
    puts o.key
  end

rescue Aws::S3::Errors::ServiceError
  # rescues all errors returned by Amazon Simple Storage Service
end

我连接到S3没有问题。我设置了我的区域和凭据。但是我无法上传一个简单的文件。 - R.J. Robinson
你想定义s3的是客户端,而不是资源。 - Antarr Byrd
谢谢,不过... ➜ s3-tester ruby main.rb main.rb:14:in <main>': #<Aws::S3::Client>没有buckets'方法 (NoMethodError) - R.J. Robinson
好的,我目前使用版本1,我会尝试解决差异。 - Antarr Byrd
➜ s3-tester ruby main.rb /Users/RJ/.rvm/gems/ruby-2.1.1/gems/aws-sdk-resources-2.0.34/lib/aws-sdk-resources/collection.rb:79:in method_missing': undefined method []' for #Aws::Resources::Collection:0x00000102d722f8 (NoMethodError) from main.rb:15:in `<main>' - R.J. Robinson

0
简短回答:您应该添加一个方法来检查存储桶是否已经存在。这样做可以遵循最佳实践,最小化失败的风险。
代码示例如下:
client = Aws::S3::Client.new(http_wire_trace: true) // Note: Enable wire_trace only in debug mode.
    
create_bucket_if_missing(client, bucket_name)

client.put_object(
     :bucket => bucket_name,
     :key    => key,
     :body   => File.read(file_path)
   )

def create_bucket_if_missing(client, bucket_name)
  begin
    client.head_bucket(bucket: bucket_name)
    return
  rescue StandardError
    puts "Failed to find bucket #{bucket_name}, creating it"
    client.create_bucket({bucket: bucket_name})
  end
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接