简体   繁体   English

AWS Ruby SDK 核心:将文件上传到 S3

[英]AWS Ruby SDK CORE: Upload files to S3

I want to upload a file (any file, could be a .txt, .mp4, .mp3, .zip, .tar ...etc) to AWS S3 using AWS-SDK-CORE ruby SDK我想使用AWS-SDK-CORE ruby​​ SDK将文件(任何文件,可以是 .txt、.mp4、.mp3、.zip、.tar ...等)上传到 AWS S3

Here is my code:这是我的代码:

require 'aws-sdk-core'
Aws.config = {
  :access_key_id => MY_ACCESS_KEY
  :secret_access_key => MY_SECRET_KEY,
  :region => 'us-west-2'
}

s3 = Aws::S3.new
resp = s3.put_object(
  :bucket => "mybucket",
  :key => "myfolder/upload_me.sql",
  :body => "./upload_me.sql"
)

Now, Above code runs and creates a key myfolder/upload_me.sql which has only one line written and that is ./upload_me.sql which is wrong.现在,上面的代码运行并创建了一个关键的myfolder/upload_me.sql ,它只写了./upload_me.sql ,这是错误的./upload_me.sql The file upload_me.sql has several lines.文件upload_me.sql有几行。

Expected behaviour is to upload the file upload_me.sql on S3 as mybucket/myfolder/upload_me.sql .预期行为是在 S3 mybucket/myfolder/upload_me.sql文件upload_me.sql上传为mybucket/myfolder/upload_me.sql But instead it just writes one line to mybucket/myfolder/upload_me.sql and that is ./upload_me.sql但它只是向mybucket/myfolder/upload_me.sql写入一行,即./upload_me.sql

Now, If I omit the :body part as below:现在,如果我省略:body部分如下:

s3 = Aws::S3.new
resp = s3.put_object(
  :bucket => "mybucket",
  :key => "myfolder/upload_me.sql",
)

Then it just creates and empty key called mybucket/myfolder/upload_me.sql which is not even downloadable (well, even if it gets downloaded, it is useless)然后它只是创建一个名为mybucket/myfolder/upload_me.sql空密钥,该密钥甚至不可下载(好吧,即使它被下载,它也没用)

Could you point me where I am going wrong?你能指出我哪里出错了吗?

Here is ruby-SDK-core documentation for put_object Method: http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/V20060301.html#put_object-instance_method这是put_object方法的 ruby​​-SDK-core 文档: http : put_object

UPDATE: If I try to upload the same file using AWS-CLI, it gets uploaded fine.更新:如果我尝试使用 AWS-CLI 上传相同的文件,它会上传得很好。 Here is the command:这是命令:

aws s3api put-object --bucket mybucket --key myfolder/upload_me.sql --body ./upload_me.sql

So, After spending a frustrating sunday afternoon on htis issue, I finally cracked it.所以,在 htis 问题上度过了一个令人沮丧的周日下午之后,我终于破解了它。 What I really needed is :body => IO.read("./upload_me.sql")我真正需要的是:body => IO.read("./upload_me.sql")

So my code looks like below:所以我的代码如下所示:

s3 = Aws::S3.new
resp = s3.put_object(
  :bucket => "mybucket",
  :key => "myfolder/upload_me.sql",
  :body => IO.read("./upload_me.sql")
)

The body variable is the contents that will be written to S3. body 变量是将写入 S3 的内容。 So if you send a file to S3 you need to manually load by using File.read("upload_me.sql") something similar.因此,如果您将文件发送到 S3,您需要使用 File.read("upload_me.sql") 类似的东西手动加载。

s3 = Aws::S3.new
resp = s3.put_object(
  :bucket => "mybucket",
  :key => "myfolder/upload_me.sql",
  :body => File.read("./upload_me.sql")
)

According to the documentation another way to do this is to use write on the bucket.根据文档,另一种方法是在存储桶上使用 write 。

s3 = AWS::S3.new
key = File.basename(file_name)
s3.buckets["mybucket"].objects[key].write(:file => "upload_me.sql")

Another way would be另一种方式是

AWS.config(
    :access_key_id => 'MY_ACCESS_KEY',
    :secret_access_key => 'MY_SECRET_KEY',
)

#Set the filename
file_name = 'filename.txt'

#Set the bucket name
s3_bucket_name = 'my bucket name'

#If file has to go in some specific folder
bucket_directory = 'key or folder'

begin
  s3 = AWS::S3.new

  #Check if directory name has provided and Make an object in your bucket for your upload
  if bucket_directory == ''
    bucket_obj = s3.buckets[s3_bucket_name].objects[bucket_directory]
  else
    bucket_obj = s3.buckets[s3_bucket_name].objects["#{bucket_directory}/#{file_name}"]
  end

  # Upload the file
  bucket_obj.write(:file => file_name)
  puts "File was successfully uploaded : #{bucket_obj}"
rescue Exception => e
  puts "There was an error in uploading file: #{e}"
end

Working Example 工作示例

Reference 参考

Probably the file wasn't found as the path is relative.由于路径是相对的,因此可能找不到该文件。 This is a strange behavior, where the interface try to make too many decisions.这是一种奇怪的行为,界面试图做出太多决定。

I can assure you this works (v3):我可以向你保证这有效(v3):

client = Aws::S3::Client.new(...)
client.put_object(
  body: './existing_file.txt',
  bucket: 'kick-it',
  key: 'test1.txt'
) # kick-it:/test1.txt contains the same as the contents of existing_file.txt

client.put_object(
  body: './non_existing_file.txt',
  bucket: 'kick-it',
  key: 'test2.txt'
) # kick-it:/test2.txt contains just the string './non_existing_file.txt'

Using body for both cases is a bad decision, if you ask me.如果你问我,在这两种情况下都使用 body 是一个错误的决定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM