Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upload to S3 with progress in plain Ruby script

This question is related to this one: Tracking Upload Progress of File to S3 Using Ruby aws-sdk,

However since there is no clear solution to this I was wondering if there's a better/easier way (if one exists) of getting file upload progress with S3 using Ruby in 2018?

In my current setup I'm basically creating a new Resource, fetch my bucket and call upload_file but I haven't yet found any options for passing blocks which would help in yielding some sort of progress.

...
@connection = Aws::S3::Resource.new
@s3_bucket = @connection.bucket(bucket)
@s3_bucket.object(path).upload_file(data, {acl: 'public-read'})
...

Is there a way to do this using the newest sdk-for-ruby v3?

Any help (or even better a small example) would be great.

like image 360
stratis Avatar asked May 09 '18 12:05

stratis


People also ask

Is S3 upload asynchronous?

For example, the Amazon S3 method PutObject is synchronous, while PutObjectAsync is asynchronous. Like all asynchronous operations, an asynchronous SDK method returns before its main task is finished. For example, the PutObjectAsync method returns before it finishes uploading the file to the Amazon S3 bucket.

How much data you can upload through simple upload in S3?

You can upload any file type—images, backups, data, movies, etc. —into an S3 bucket. The maximum size of a file that you can upload by using the Amazon S3 console is 160 GB. To upload a file larger than 160 GB, use the AWS CLI, AWS SDK, or Amazon S3 REST API.

What is S3 direct upload?

Amazon S3 Direct Upload for Web UI is an addon that allows Web UI to make use of S3 Direct Upload to directly upload files to a transient bucket, which will then be moved by the Nuxeo server to a final bucket once the upload is finished.


1 Answers

The example Trevor gives in https://stackoverflow.com/a/12147709/153886 is not hacky from what I can see - just wiring things together. The SDK simply does not provide a feature for passing progress details on all operations. Plus, Trevor is the maintainer of the Ruby SDK at AWS so I trust his judgement.

Expanding on his example

bar = ProgressBar.create(:title => "Uploading action", :starting_at => 0, :total => file.size)
obj = s3.buckets['my-bucket'].objects['object-key']
obj.write(:content_length => file.size) do |writable, n_bytes|
  writable.write(file.read(n_bytes))
  bar.progress += n_bytes
end

If you want to have a progress block right in the upload_file method I believe you will need to open a PR to the SDK. It is not that strange that is not the case for Ruby (or for any other runtime) because, for example, there could be an optimisation in the HTTP client library that uses IO.copy_stream from your source body argument to the destination socket, which does not relay progress anywhere.

like image 118
Julik Avatar answered Nov 05 '22 08:11

Julik