diff options
author | George Claghorn <george.claghorn@gmail.com> | 2018-05-01 23:20:56 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-01 23:20:56 -0400 |
commit | bf5f41d948b6f3f27db7fdc2b70897aec991065f (patch) | |
tree | eb3fcfe108b84147331e1ee58f384e41318084d1 /activestorage/lib | |
parent | db7416cda0700876ad3438774b804eb80a05a758 (diff) | |
download | rails-bf5f41d948b6f3f27db7fdc2b70897aec991065f.tar.gz rails-bf5f41d948b6f3f27db7fdc2b70897aec991065f.tar.bz2 rails-bf5f41d948b6f3f27db7fdc2b70897aec991065f.zip |
Support streaming downloads from Google Cloud Storage
Diffstat (limited to 'activestorage/lib')
-rw-r--r-- | activestorage/lib/active_storage/service/gcs_service.rb | 44 |
1 files changed, 25 insertions, 19 deletions
diff --git a/activestorage/lib/active_storage/service/gcs_service.rb b/activestorage/lib/active_storage/service/gcs_service.rb index 7a1839a1aa..38acef81f4 100644 --- a/activestorage/lib/active_storage/service/gcs_service.rb +++ b/activestorage/lib/active_storage/service/gcs_service.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -gem "google-cloud-storage", "~> 1.8" +gem "google-cloud-storage", "~> 1.11" require "google/cloud/storage" require "net/http" @@ -32,28 +32,21 @@ module ActiveStorage end end - # FIXME: Download in chunks when given a block. - def download(key) - instrument :download, key: key do - io = file_for(key).download - io.rewind - - if block_given? - yield io.string - else - io.string + def download(key, &block) + if block_given? + instrument :streaming_download, key: key do + stream(key, &block) + end + else + instrument :download, key: key do + file_for(key).download.string end end end def download_chunk(key, range) instrument :download_chunk, key: key, range: range do - file = file_for(key) - uri = URI(file.signed_url(expires: 30.seconds)) - - Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |client| - client.get(uri, "Range" => "bytes=#{range.begin}-#{range.exclude_end? ? range.end - 1 : range.end}").body - end + file_for(key).download(range: range).string end end @@ -111,8 +104,21 @@ module ActiveStorage private attr_reader :config - def file_for(key) - bucket.file(key, skip_lookup: true) + def file_for(key, skip_lookup: true) + bucket.file(key, skip_lookup: skip_lookup) + end + + # Reads the file for the given key in chunks, yielding each to the block. + def stream(key) + file = file_for(key, skip_lookup: false) + + chunk_size = 5.megabytes + offset = 0 + + while offset < file.size + yield file.download(range: offset..(offset + chunk_size - 1)).string + offset += chunk_size + end end def bucket |