DigitalOceanSpacesを使用してRails6でActiveStorageを使用する方法
著者は、 Diversity in Tech Fund を選択して、 Write forDOnationsプログラムの一環として寄付を受け取りました。
序章
ユーザーがファイルをアップロードして保存できるWebアプリケーションを構築する場合は、スケーラブルなファイルストレージソリューションを使用する必要があります。 これにより、アプリケーションの人気が非常に高くなった場合でも、スペースが不足する危険がなくなります。 結局のところ、これらのアップロードは、プロフィール写真から家の写真、PDFレポートまで何でもかまいません。 また、ファイルストレージソリューションの信頼性を高めて、重要な顧客ファイルを失わないようにし、訪問者がファイルの転送を待たないようにする必要があります。 これもすべて手頃な価格にしたいと思います。
DigitalOcean Spaces は、これらすべてのニーズに対応できます。 AmazonのS3サービスと互換性があるため、Rails6に付属する新しいActiveStorage ライブラリを使用して、RubyonRailsアプリケーションにすばやく統合できます。
このガイドでは、Railsアプリケーションを構成して、DigitalOceanSpacesでActiveStorageを使用するようにします。 次に、直接アップロードとSpacesの組み込みCDN(コンテンツ配信ネットワーク)を使用して、アップロードとダウンロードを高速に取得するために必要な構成を実行します。
終了すると、ファイルストレージとDigitalOceanスペースを独自のRailsアプリケーションに統合する準備が整います。
前提条件
このガイドを開始する前に、次のものが必要です。
- DigitalOceanアカウント。
- RubyonRailsの開発環境。 使用しているオペレーティングシステムに応じて、macOSでRbenvを使用してRubyonRailsをインストールする方法またはUbuntuでRbenvを使用してRubyonRailsをインストールする方法に従ってください。
- RubyonRailsに関する初期の知識。 Ruby on Railsアプリケーションの構築方法などのチュートリアルがこれに役立ちます。または、公式スタートガイドに従うこともできます。
- 開発マシンにGitがインストールされています。 チュートリアルオープンソースへの貢献:Git入門に従って、コンピューターにGitをインストールしてセットアップすることができます。
- Node.jsがインストールされています。これは、Node.jsのインストール方法とローカル開発環境の作成方法に従って実行できます。 このチュートリアルでは、Node.jsバージョン14を使用します。
npm install -g yarn
でインストールできるYarnパッケージマネージャーがインストールされています。- SQLiteがインストールされています。これは、 RubyonRailsアプリケーションを構築する方法のステップ1に従って実行できます。
- Imagemagickがインストールされています。これは、チュートリアルImageMagickを使用して画像のサイズを変更する方法に従ってインストールできます。
- (オプション)Spaces CDNを試してみたい場合は、ドメイン名とそのドメインのDNSレコードを変更する機能が必要です。 ドメインの追加方法チュートリアルに従って、DigitalOceanでドメインを管理できます。
- (オプション)直接アップロードを使用する場合は、DigitalOceanSpacesで動作するように
s3cmd
を構成する必要があります。 DigitalOcean Spacesを使用したs3cmd2.xのセットアップに従って、セットアップを行います。
ステップ1—サンプルアプリを実行する
完全なRailsアプリケーションを最初から構築するのではなく、ActiveStorageを使用する既存のRails 6アプリケーションのクローンを作成し、それを変更して、イメージストレージバックエンドとしてDigitalOceanSpacesを使用します。 使用するアプリはSpacePuppies です。これは、お気に入りの子犬の写真をアップロードして表示できる画像ギャラリーです。 アプリケーションは次の図のようになります。
ターミナルを開き、次のコマンドを使用してGitHubからアプリケーションのクローンを作成します。
git clone https://github.com/do-community/space-puppies
次のような出力が表示されます。
OutputCloning into 'space-puppies'... remote: Enumerating objects: 122, done. remote: Counting objects: 100% (122/122), done. remote: Compressing objects: 100% (103/103), done. remote: Total 122 (delta 3), reused 122 (delta 3), pack-reused 0 Receiving objects: 100% (122/122), 163.17 KiB | 1018.00 KiB/s, done. Resolving deltas: 100% (3/3), done.
次に、Rubyのバージョンを確認します。 SpacePuppiesはRuby2.7.1を使用しているため、rbenv versions
を実行して、インストールしたバージョンを確認します。
rbenv versions
前提条件のチュートリアルに従っている場合、そのリストにはRuby 2.5.1しか含まれておらず、出力は次のようになります。
Output* system 2.5.1
そのリストにRuby2.7.1が含まれていない場合は、ruby-build
を使用してインストールしてください。
rbenv install 2.7.1
お使いのマシンの速度とオペレーティングシステムによっては、これには時間がかかる場合があります。 次のような出力が表示されます。
OutputDownloading ruby-2.7.1.tar.bz2... -> https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.1.tar.bz2 Installing ruby-2.7.1... Installed ruby-2.7.1 to /root/.rbenv/versions/2.7.1
space-puppies
ディレクトリに移動します。
cd space-puppies
rbenv
は、ディレクトリに入ると自動的にRubyのバージョンを変更します。 バージョンを確認します。
ruby --version
次のような出力が表示されます。
Outputruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]
次に、アプリの実行に必要なRubygemsとJavaScriptパッケージをインストールします。 次に、SpacePuppiesアプリを実行するために必要なデータベースの移行を行います。
bundle
コマンドを使用して、必要なすべてのgemをインストールします。
bundle install
次に、Bundlerによってインストールされた新しいバイナリについてrbenv
に通知するには、rehash
コマンドを使用します。
rbenv rehash
次に、yarn
に必要なJavaScript依存関係をインストールするように指示します。
yarn install
次に、Railsの組み込み移行ツールを使用してデータベーススキーマを作成します。
rails db:migrate
すべてのライブラリがインストールされ、データベースが作成されたら、次のコマンドを使用して組み込みのWebサーバーを起動します。
rails s
注:デフォルトでは、rails s
はローカルループバックアドレスにのみバインドします。つまり、コマンドを実行する同じコンピューターからのみサーバーにアクセスできます。 ドロップレットで実行していて、ローカルマシンで実行されているブラウザからサーバーにアクセスする場合は、0.0.0.0
にバインドしてリモートリクエストに応答するようにRailsサーバーに指示する必要があります。 あなたはこのコマンドでそれをすることができます:
rails s -b 0.0.0.0
サーバーが起動し、次のような出力が表示されます。
Output=> Booting Puma => Rails 6.0.3.2 application starting in development => Run `rails server --help` for more startup options Puma starting in single mode... * Version 4.3.5 (ruby 2.7.1-p83), codename: Mysterious Traveller * Min threads: 5, max threads: 5 * Environment: development * Listening on tcp://127.0.0.1:3000 * Listening on tcp://[::1]:3000 Use Ctrl-C to stop
これで、Webブラウザでアプリケーションにアクセスできます。 ローカルマシンでアプリケーションを実行している場合は、http://localhost:3000
に移動します。 ドロップレットまたはその他のリモートサーバーで実行している場合は、http://your_server_ip:3000
に移動します。
アプリのインターフェースが表示されますが、今回は子犬がいません。 New Puppy ボタンをクリックして、画像をいくつか追加してみてください。
テストに使用する子犬の写真が必要な場合は、Unsplashにテストに使用できる広範なリストがあります。 プロジェクトでこれらのイメージを使用する場合は、Unsplashライセンスを確認してください。
先に進む前に、アプリケーションの各レイヤーを見ていき、ActiveStorageが各部分でどのように機能するかを見て、DigitalOceanSpacesに必要な変更を加えることができるようにします。 ActiveStorageの詳細については、Railsの公式ドキュメントの Active StorageOverviewページを参照してください。
まず、データベースに保存しているアプリケーション内のオブジェクトを表すモデルを確認します。 Puppy
モデルはapp/models/puppy.rb
にあります。 このファイルをテキストエディタで開くと、次のコードが表示されます。
app / models / puppy.rb
class Puppy < ApplicationRecord has_one_attached :photo end
モデルにはhas_one_attached
マクロがあります。これは、各Puppy
モデルインスタンスに写真が添付されていることを示しています。 これらの写真は、ActiveStorage::Attached::One
プロキシを介してActiveStorage::Blob
インスタンスとして保存されます。
このファイルを閉じます。
スタックの次の層はコントローラーです。 Railsアプリケーションでは、コントローラーはデータベースモデルへのアクセスを制御し、ユーザーからの要求に応答する責任があります。 Puppy
モデルに対応するコントローラーは、app/controllers/puppies_controller.rb
にあるPuppiesController
です。 このファイルをエディターで開くと、次のコードが表示されます。
app / controllers / puppies_controller.rb
class PuppiesController < ApplicationController def index @puppies = Puppy.with_attached_photo end # ... snipped other actions ... end
with_attached_photo
呼び出しを除いて、ファイル内のすべてが標準のRailsコードです。 この呼び出しにより、Puppy
モデルのリストをフェッチするときに、ActiveRecordは関連するすべてのActiveStorage::Blob
アソシエーションをロードします。 これは、ActiveStorageが提供するスコープであり、高価な N+1データベースクエリを回避するのに役立ちます。
最後に、アプリケーションがユーザーのブラウザーに送信するHTMLを生成するビューを見てみましょう。 このアプリにはいくつかのビューがありますが、アップロードされた子犬の画像を表示するためのビューに焦点を当てる必要があります。 このファイルはapp/views/puppies/_puppy.html.erb
にあります。 エディターで開くと、次のようなコードが表示されます。
app / views / puppies / _puppy.html.erb
<div class="puppy"> <%= image_tag puppy.photo.variant(resize_to_fill: [250, 250]) %> </div>
ActiveStorageはRailsと連携するように設計されているため、組み込みのimage_tag
ヘルパーを使用して、写真が保存されている場所に関係なく、添付された写真を指すURLを生成できます。 この場合、アプリは画像にバリアントサポートを使用しています。 ユーザーが最初にこのバリアントをリクエストすると、ActiveStorageは image_processing gemを介してImageMagickを自動的に使用し、要件に合った変更された画像を生成します。 この場合、250x250ピクセルのボックスを埋める子犬の写真が作成されます。 バリアントは元の写真と同じ場所に保存されます。つまり、各バリアントを生成する必要があるのは1回だけです。 Railsは、後続のリクエストで生成されたバージョンを提供します。
注:画像のバリエーションの生成は遅くなる可能性があり、ユーザーを待たせたくない場合があります。 特定のバリアントが必要になることがわかっている場合は、.processed
メソッドを使用して熱心に生成できます。
puppy.photo.variant(resize_to_fill: [250, 250]).processed
本番環境にデプロイするときは、この種の処理をバックグラウンドジョブで実行することをお勧めします。 アクティブジョブを調べ、processed
を呼び出して事前に画像を生成するタスクを作成します。
これで、アプリケーションがローカルで実行され、すべてのコード部分がどのように組み合わされるかがわかります。 次に、アップロードをクラウドに移動できるように、新しいDigitalOceanSpaceをセットアップします。
ステップ2—DigitalOceanスペースを設定する
現時点では、Space Puppiesアプリケーションは画像をローカルに保存します。これは開発やテストには問題ありませんが、本番環境でこのモードを使用することはほぼ間違いありません。 アプリケーションサーバーインスタンスを追加してアプリケーションを水平方向にスケーリングするには、すべてのサーバーに各イメージのコピーが必要です。
このステップでは、アプリの画像に使用するDigitalOceanスペースを作成します。
DigitalOcean管理コンソールにサインインし、右上の作成をクリックして、スペースを選択します。
データセンターを選択し、CDNを今のところ無効のままにします。 後でこれに戻ります。 ファイルリストがファイルリストの制限に設定されていることを確認します。
スペースの名前を選択してください。 これはすべてのSpacesユーザー間で一意である必要があるため、yourname-space-puppies
のように一意の名前を選択してください。 スペースの作成をクリックします。
警告:顧客に代わって保存するファイルへのアクセスに注意してください。 ファイルストレージの設定ミスによるデータ漏洩やハッキングの例が数多くあります。 デフォルトでは、ActiveStorageファイルにアクセスできるのは、認証されたURLを生成した場合のみですが、顧客データを扱う場合は注意が必要です。
次に、新しいスペースが表示されます。
設定タブをクリックして、スペースのエンドポイントをメモします。 Railsアプリケーションを構成するときに必要になります。
次に、このスペースにActiveStorageファイルを保存するようにRailsアプリケーションを構成します。 これを安全に行うには、新しいSpacesアクセスキーとシークレットを作成する必要があります。
左側のナビゲーションでAPIをクリックし、右下の新しいキーの生成をクリックします。 新しいキーに「DevelopmentMachine」のようなわかりやすい名前を付けます。 あなたの秘密は一度だけ現れるので、しばらくの間安全な場所にそれをコピーすることを忘れないでください。
Railsアプリでは、そのアクセストークンを安全に保存する方法が必要になるため、Railsの安全な資格情報管理機能を使用します。 資格情報を編集するには、端末で次のコマンドを実行します。
EDITOR="nano -w" rails credentials:edit
これにより、マスターキーが生成され、nano
エディターが起動して、値を編集できるようになります。
nano
で、APIキーとDigitalOceanのシークレットを使用して、credentials.yml
ファイルに以下を追加します。
config / credentials.yml
digitalocean: access_key: YOUR_API_ACCESS_KEY secret: YOUR_API_ACCESS_SCRET
ファイルを保存して閉じます(Ctrl+X
、Y
、Enter
)。Railsは暗号化されたバージョンを保存し、config/credentials.yml.enc
でソース管理に安全にコミットできます。 ]。
次のような出力が表示されます。
Output Adding config/master.key to store the encryption key: RANDOM_HASH_HERE Save this in a password manager your team can access. If you lose the key, no one, including you, can access anything encrypted with it. create config/master.key File encrypted and saved.
クレデンシャルを構成したので、アプリを新しいSpacesバケットにポイントする準備が整いました。
エディターでファイルconfig/storage.yml
を開き、そのファイルの最後に次の定義を追加します。
config / storage.yml
digitalocean: service: S3 endpoint: https://your-spaces-endpoint-here access_key_id: <%= Rails.application.credentials.dig(:digitalocean, :access_key) %> secret_access_key: <%= Rails.application.credentials.dig(:digitalocean, :secret) %> bucket: your-space-name-here region: unused
サービスはSpaces
ではなくS3
と言っていることに注意してください。 SpacesにはS3互換のAPIがあり、RailsはS3をネイティブにサポートしています。 エンドポイントはhttps://
の後に、前にコピーしたスペースのエンドポイントが続きます。bucket
の名前は、スペースの作成時に入力したスペースの名前です。 スペースを表示すると、コントロールパネルにバケット名もタイトルとして表示されます。
この構成ファイルは暗号化されずに保存されるため、アクセスキーとシークレットを入力する代わりに、credentials.yml.enc
に安全に入力したものを参照します。
注:DigitalOceanは、エンドポイントを使用してリージョンを指定します。 ただし、リージョンを指定する必要があります。指定しないと、ActiveStorageが文句を言います。 DigitalOceanはそれを無視するので、好きな値に設定できます。 サンプルコードの値unused
は、それを使用していないことを明確に示しています。
構成ファイルを保存します。
次に、ローカルファイルシステムではなく、ファイルストレージバックエンドにSpacesを使用するようにRailsに指示する必要があります。 エディタでconfig/environments/development.rb
を開き、config.active_storage.service
エントリを:local:
から:digitalocean
に変更します。
config / environment / development.rb
# ... # Store uploaded files on the local file system (see config/storage.yml for options). config.active_storage.service = :digitalocean # ...
ファイルを保存して、エディターを終了します。 サーバーを再起動します。
rails s -b 0.0.0.0
ブラウザでもう一度http://localhost:3000
またはhttp://your server ip:3000
にアクセスします。
いくつかの画像をアップロードすると、アプリはそれらをDigitalOceanSpaceに保存します。 これは、DigitalOceanコンソールでスペースにアクセスすると確認できます。 アップロードされたファイルとバリアントが一覧表示されます。
ActiveStorageはデフォルトでランダムなファイル名を使用します。これは、アップロードされた顧客データを保護する場合に役立ちます。 代わりに、元のファイル名を含むメタデータがデータベースに保存されます。
注: Aws::S3::Errors::SignatureDoesNotMatch
を取得している場合は、資格情報が正しくない可能性があります。 rails credentials:edit
を再度実行し、それらを再確認します。
Railsは、ファイルの名前と一部のメタデータをActiveStorage::Blob
レコードとして保存します。 添付ファイルにちなんで名付けられたアクセサメソッドを呼び出すことにより、任意のレコードのActiveStorage::Blob
にアクセスできます。 この場合、添付ファイルはphoto
と呼ばれます。
やってみよう。 ターミナルでRailsコンソールを起動します。
rails c
アップロードした最後の子犬の写真からブロブを取得します。
> Puppy.last.photo.blob #=> => #<ActiveStorage::Blob ...>
これで、アップロードをスケーラブルで信頼性が高く、手頃な価格のオブジェクトストアに保存するRailsアプリケーションができました。
次の2つのステップでは、このソリューションのパフォーマンスとユーザーの速度を向上させるのに役立つ、アプリに追加できる2つのオプションについて説明します。
ステップ3— Spaces CDNの設定(オプション)
注:この手順では、DigitalOceanを指すネームサーバーを備えたドーマンが必要です。 ドメインの追加方法ガイドに従ってください。
コンテンツ配信ネットワーク(CDN)を使用すると、ファイルのコピーをユーザーの近くに配置することで、ユーザーがファイルをより高速にダウンロードできるようになります。
Uptrends CDN PerformanceCheckなどのツールを使用してCDNパフォーマンスを調査できます。 前の手順でアップロードした写真のいずれかのURLを追加すると、近くにいる場合は高速であることがわかりますが、地理的に離れるにつれて状況は少し遅くなります。 URLは、ブラウザーの開発者ツールを使用するか、Railsコンソール(rails c
)を起動して、添付ファイルでservice_url
を呼び出すことで取得できます。
> Puppy.last.photo.service_url
これは、サンフランシスコのデータセンターにあるファイルを使用した上昇傾向レポートの例です。 サンフランシスコからの距離に応じて時間が減少することに注意してください。 サンディエゴの時間は短いですが、パリの時間ははるかに長いです。
Spacesの組み込みCDNを有効にすることで、速度を向上させることができます。 DigitalOceanコントロールパネルのSpacesに移動し、手順2で作成したスペースの名前をクリックします。 次に、設定タブを選択し、 CDN(コンテンツ配信ネットワーク)の横にある編集をクリックしてから、CDNを有効にするをクリックします。
次に、CDNに使用するドメインを選択し、そのドメインのSSL証明書を作成する必要があります。 これは、 Let'sEncryptを使用して自動的に行うことができます。 [カスタムサブドメインを使用する]ドロップダウンをクリックしてから、新しいサブドメイン証明書を追加するをクリックします。
使用するドメインを見つけて、サブドメインを作成するオプションを選択します。 cdn.yourdomain.com
のようなものは、標準の命名規則です。 次に、証明書に名前を付けて、[証明書を生成してサブドメインを使用する]ボタンをクリックします。
CDN(コンテンツ配信ネットワーク)の下にある保存ボタンを押します。
これでCDNが有効になりましたが、RailsアプリケーションにCDNを使用するように指示する必要があります。 これは、このバージョンのRailsではActiveStorageに組み込まれていないため、いくつかの組み込みRailsフレームワークメソッドをオーバーライドして機能させます。
config/initializers/active_storage_cdn.rb
という名前の新しいRails初期化子を作成し、URLを書き換える次のコードを追加します。
config / initializers / active_storage_cdn.rb
Rails.application.config.after_initialize do require "active_storage/service/s3_service" module SimpleCDNUrlReplacement CDN_HOST = "cdn.yourdomain.com" def url(...) url = super original_host = "#{bucket.name}.#{client.client.config.endpoint.host}" url.gsub(original_host, CDN_HOST) end end ActiveStorage::Service::S3Service.prepend(SimpleCDNUrlReplacement) end
この初期化子は、アプリケーションがActiveStorage::Service::S3Service
プロバイダーからのURLを要求するたびに実行されます。 次に、元の非CDNホストを、CDN_HOST
定数として定義されているCDNホストに置き換えます。
これでサーバーを再起動できます。各写真がCDNからのものであることがわかります。 スペースを設定したデータセンターからエッジノードにコンテンツを転送するのはDigitalOceanが処理するため、これらを再アップロードする必要はありません。
Uptrendsのパフォーマンスチェックサイトで写真にアクセスする速度を、CDN以前の速度と比較することをお勧めします。 サンフランシスコを拠点とするスペースでCDNを使用する例を次に示します。 グローバルな速度が大幅に向上していることがわかります。
次に、ブラウザから直接ファイルを受信するようにアプリケーションを構成します。
ステップ4—直接アップロードの設定(オプション)
検討したいActiveStorageの最後の機能は直接アップロードと呼ばれます。 これで、ユーザーがファイルをアップロードすると、データがサーバーに送信され、Railsによって処理されてから、Spaceに転送されます。 これは、多数の同時ユーザーがいる場合、またはユーザーが大きなファイルをアップロードしている場合に問題を引き起こす可能性があります。各ファイルは(ほとんどの場合)アップロードの全期間にわたって単一のアプリサーバースレッドを使用するためです。
対照的に、直接アップロードは、Railsサーバーホップを介さずにDigitalOceanSpaceに直接送信されます。 これを行うには、Railsに付属する組み込みのJavaScriptを有効にして、クロスオリジンリソースシェアリングを構成します([CORS](( https://developer.mozilla.org/en-US/docs/Webスペースの/HTTP/ CORS )。これにより、リクエストが別の場所から発信されている場合でも、リクエストをスペースに直接安全に送信できます。
まず、スペースのCORSを構成します。 これを行うにはs3cmd
を使用します。これをスペースで動作するように構成していない場合は、DigitalOceanSpacesを使用したs3cmd2.xのセットアップに従うことができます。
cors.xml
という名前の新しいファイルを作成し、次のコードをファイルに追加して、your_domain
を開発に使用しているドメインに置き換えます。 ローカルマシンで開発している場合は、http://localhost:3000
を使用します。 ドロップレットで開発している場合、これはドロップレットのIPアドレスになります。
cors.xml
<CORSConfiguration> <CORSRule> <AllowedOrigin>your_domain</AllowedOrigin> <AllowedMethod>PUT</AllowedMethod> <AllowedHeader>*</AllowedHeader> <ExposeHeader>Origin</ExposeHeader> <ExposeHeader>Content-Type</ExposeHeader> <ExposeHeader>Content-MD5</ExposeHeader> <ExposeHeader>Content-Disposition</ExposeHeader> <MaxAgeSeconds>3600</MaxAgeSeconds> </CORSRule> </CORSConfiguration>
次に、s3cmd
を使用して、これをスペースのCORS構成として設定できます。
s3cmd setcors cors.xml s3://your-space-name-here
このコマンドが正常に実行された場合、出力はありませんが、DigitalOceanコントロールパネルでスペースを確認することで、コマンドが機能したことを確認できます。 スペースを選択し、スペースの名前を選択してから、設定タブを選択します。 CORSConfigurationsの見出しの下に設定が表示されます。
注:現時点では、コントロールパネルではなくs3cmd
を使用して、「localhost」ドメインのCORSを構成する必要があります。これは、コントロールパネルがこれらを無効なドメインとして扱うためです。 ローカルホスト以外のドメイン(Droplet IPなど)を使用している場合は、ここで安全に実行できます。
次に、direct_upload
オプションをfile_field
ヘルパーに渡すことにより、直接アップロードを使用するようにRailsに指示する必要があります。 エディタでapp/views/puppies/new.html.erb
を開き、file_field
ヘルパーを変更します。
app / views / puppies / new.html.erb
<h2>New Puppy</h2> <%= form_with(model: @puppy) do |f| %> <div class="form-item"> <%= f.label :photo %> <%= f.file_field :photo, accept: "image/*", direct_upload: true %> </div> <div class="form-item"> <%= f.submit "Create puppy", class: "btn", data: { disable_with: "Creating..." } %> </div> <% end %>
ファイルを保存して、サーバーを再起動します。
rails s -b 0.0.0.0
新しい写真をアップロードすると、写真はDigitalOceanSpacesに直接アップロードされます。 これは、子犬の作成ボタンをクリックしたときに行われるPUT
リクエストを確認することで確認できます。 ブラウザのWebコンソールを確認するか、Railsサーバーのログを読み取ることで、リクエストを見つけることができます。 特に大きな画像の場合、画像のアップロードが大幅に高速化されていることに気付くでしょう。
結論
この記事では、ActiveStorageを使用して基本的なRailsアプリケーションを変更し、DigitalOcean Spacesで安全、高速、スケーラブルなファイルを保存しました。 ユーザーがどこにいても高速ダウンロード用にCDNを構成し、アプリサーバーが圧倒されないように直接アップロードを実装しました。
これで、このコードと構成を取得して、独自のRailsアプリケーションに適合するように適合させることができます。