加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

使用Ruby将大文件上传到S3失败,出现内存不足错误,如何在块中读取

发布时间:2020-12-17 02:48:10 所属栏目:百科 来源:网络整理
导读:我们通过 Ruby AWS SDK(v2)从Windows机器上传各种文件到S3.我们已经使用Ruby 1.9进行了测试.我们的代码工作正常,除非遇到大文件,抛出内存不足错误. 起初我们使用以下代码将整个文件读入内存: :body = IO.binread(filepath), 然后在Googling之后我们发现有很
我们通过 Ruby AWS SDK(v2)从Windows机器上传各种文件到S3.我们已经使用Ruby 1.9进行了测试.我们的代码工作正常,除非遇到大文件,抛出内存不足错误.

起初我们使用以下代码将整个文件读入内存:

:body => IO.binread(filepath),

然后在Googling之后我们发现有很多方法可以用Ruby读取文件:

:body =>  File.open(filepath,'rb') { |io| io.read },

但是,此代码无法解决问题,我们无法找到特定的S3(或相关)示例,该示例显示了如何读取文件并以块的形式传递给S3.整个文件仍然加载到内存中,并在大文件中引发内存不足错误.

我们知道我们可以将文件拆分成块并使用AWS多部分上传上传到S3,但是如果可能的话,首选是避免这种情况(尽管这是唯一的方法,但这样做很好).

我们的代码示例如下.以块的形式读取文件,避免内存不足错误以及上传到S3的最佳方法是什么?

require 'aws-sdk'

filepath = 'c:pathtosomelargefile.big'
bucket = 's3-bucket-name'
s3key = 'some/s3/key/file.big'
accesskeyid = 'ACCESSKEYID'
accesskey = 'ACCESSKEYHERE'
region = 'aws-region-here'

s3 = Aws::S3::Client.new(
  :access_key_id => accesskeyid,:secret_access_key => accesskey,:region => region
  )

resp = s3.put_object(
  :bucket => bucket,:key => s3key,:body =>  File.open(filepath,)

请注意,我们没有达到S3 5GB的限制,例如1.5GB的文件会发生这种情况.

解决方法

适用于Ruby的v2 AWS SDK,aws-sdk gem,直接通过网络支持流对象,而无需将其加载到内存中.您的示例只需要一个小的更正来执行此操作:

File.open(filepath,'rb') do |file|
  resp = s3.put_object(
   :bucket => bucket,:body => file
  )
end

这是有效的,因为它允许SDK在文件对象上调用#read,每次传递少量字节.在没有第一个参数的Ruby IO对象(例如文件)上调用#read会将整个对象读入内存,并将其作为字符串返回.这就是导致内存不足错误的原因.

也就是说,aws-sdk gem提供了另一个更有用的界面,用于将文件上传到Amazon S3.这个替代界面自动:

>对大对象使用多部分API
>可以使用多个线程并行上传部件,提高上传速度
>计算客户端数据的MD5以进行服务端数据完整性检查.

一个简单的例子:

# notice this uses Resource,not Client
s3 = Aws::S3::Resource.new(
  :access_key_id => accesskeyid,:region => region
)

s3.bucket(bucket).object(s3key).upload_file(filepath)

这是aws-sdk资源接口的一部分.这里有很多有用的工具. Client类仅提供基本的API功能.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读