lin*_*ndy 10 ruby csv ruby-on-rails heroku amazon-s3
我正在处理潜在的巨大CSV文件,我想从我的Rails应用程序导出,因为它在Heroku上运行,我的想法是在生成它们时将这些CSV文件直接流式传输到S3.
现在,我有一个问题,因为Aws::S3需要一个文件才能执行上传,而在我的Rails应用程序中我想做的事情如下:
S3.bucket('my-bucket').object('my-csv') << %w(this is one line)
Run Code Online (Sandbox Code Playgroud)
我怎样才能做到这一点?
Mit*_*abe 11
您可以使用 s3 分段上传,通过将大对象拆分为多个块来允许上传。 https://docs.aws.amazon.com/AmazonS3/latest/dev/mpuoverview.html
分段上传需要更复杂的编码,但 aws-sdk-ruby V3 支持upload_stream似乎在内部执行分段上传的方法,并且非常易于使用。也许这个用例的确切解决方案。
https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#upload_stream-instance_method
client = Aws::S3::Client.new(
region: 'ap-northeast-1',
credentials: your_credential
)
obj = Aws::S3::Object.new('your-bucket-here', 'path-to-output', client: client)
require "csv"
obj.upload_stream do |write_stream|
[
%w(this is first line),
%w(this is second line),
%w(this is third line),
].each do |line|
write_stream << line.to_csv
end
end
Run Code Online (Sandbox Code Playgroud)
this,is,first,line
this,is,second,line
this,is,third,line
Run Code Online (Sandbox Code Playgroud)
upload_stream块的参数通常可以用作 IO 对象,它允许您像处理文件或其他 IO 对象一样链接和包装 CSV 生成:
this,is,first,line
this,is,second,line
this,is,third,line
Run Code Online (Sandbox Code Playgroud)
或者,例如,您可以在生成和上传 CSV 时对其进行压缩,使用临时文件来减少内存占用:
obj.upload_stream do |write_stream|
CSV(write_stream) do |csv|
[
%w(this is first line),
%w(this is second line),
%w(this is third line),
].each do |line|
csv << line
end
end
end
Run Code Online (Sandbox Code Playgroud)
编辑:在压缩的示例代码中,您必须添加binmode以修复以下错误:
Aws::S3::MultipartUploadError: multipart upload failed: "\x8D" from ASCII-8BIT to UTF-8
Run Code Online (Sandbox Code Playgroud)
s3 = Aws::S3::Resource.new(region:'us-west-2')
obj = s3.bucket.object("#{FOLDER_NAME}/#{file_name}.csv")
file_csv = CSV.generate do |csv|
csv << ActionLog.column_names
ActionLog.all.each do |action_log|
csv << action_log.attributes.values
end
end
obj.put body: file_csv
Run Code Online (Sandbox Code Playgroud)
file_csv = CSV.generate是在 Ruby 中创建一串 CSV 数据。创建这个CSV字符串后,我们使用bucket放入S3,路径为
#{FOLDER_NAME}/#{file_name}.csv
Run Code Online (Sandbox Code Playgroud)
在我的代码中,我将所有数据导出到ActionLog模型中。
我会看看http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/S3/S3Object.html#write-instance_method,因为这可能就是您正在寻找的。
编辑 http://docs.aws.amazon.com/AmazonS3/latest/dev/UploadObjSingleOpRuby.html可能更相关,因为第一个链接指向ruby aws-sdk v1
require 'aws-sdk'
s3 = Aws::S3::Resource.new(region:'us-west-2')
obj = s3.bucket('bucket-name').object('key')
# string data
obj.put(body: 'Hello World!')
# IO object
File.open('source', 'rb') do |file|
obj.put(body: file)
end
Run Code Online (Sandbox Code Playgroud)