使用Ruby将大文件上传到S3失败,出现内存不足错误,如何在块中读取
我们通过
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 一个简单的例子: # 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功能. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |