【Rails】ActionTextでアップロードした画像の保存先がローカルから変更できない😥

2019年10月12日 15:53

    はじめに

    Rails6の新機能「ActionText」はお手軽にリッチテキストエディターが利用できます。
    ActionTextでアップロードした画像の保存先は、デフォルトではローカル(本番環境ならサーバー上)になっています。Railsアプリのデプロイ先としてHerokuを使うことが多いと思いますが、Herokuは定周期でデプロイ時の状態に戻していまいますので、デプロイ後にActionTextでアップロードした画像は時間が経つと消えてしまいます。
    そこで、ActionTextでアップロードした画像の保存先をローカルから外部のクラウドストレージ(今回はAmazon S3)に変更したいのですが、うまくいきませんでした😥
    現時点までに試した手順を備忘として残しておきます。もし、解決方法を知っている方がいましたら教えていただけると助かります…

    ActiveStorageについて

    ActionTextは画像のアップロードにActiveStorageを使用していますので、ActiveStorageの設定を変更していきます。

    画像の保存先を変更

    config/environments/配下にあるファイルを変更します。
    開発環境なら「development.rb」、本番環境なら「production.rb」を開きます。
      # Store uploaded files on the local file system (see config/storage.yml for options)
      config.active_storage.service = :local
    となっている行を以下のように変更します。
      # Store uploaded files on the local file system (see config/storage.yml for options)
      config.active_storage.service = :amazon

    保存先の設定を追加

    上記で変更した「:amazon」という保存先の設定を追加します。config/storage.ymlを変更します。
    # Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
    # amazon:
    #   service: S3
    #   access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
    #   secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
    #   region: us-east-1
    #   bucket: your_own_bucket
    となっている行のコメントアウトを外し、各値を設定します。
    access_key_idとsecret_access_keyはCredentialsを使って設定します。

    Credentialsの設定

    ターミナルで以下のコマンドを実行します。
    $ EDITOR=vi rails credentials:edit
    すると、Credentialsの設定がviで編集できるようになります。
    # aws:
    #   access_key_id: 123
    #   secret_access_key: 345
    となっている行のコメントアウトを外し、access_key_idとsecret_access_keyを設定します。

    CORSの設定を変更

    Amazon S3のCORSの設定はGUIからは変更できないので、コマンドラインツールのawscliを使います。
    awscliのインストールとセットアップは省略します。
    適当なディレクトリにCORS.jsonを作成し、以下のように設定します。
    {
      "CORSRules": [
        {
          "AllowedOrigins": ["http://localhost:3000"],
          "AllowedMethods": ["GET", "POST", "PUT"],
          "MaxAgeSeconds": 3000,
          "AllowedHeaders": ["*"]
        }
      ]
    }
    続いて、以下のコマンドを実行します。
    $ aws s3api put-bucket-cors --profile s3_config --bucket バケット名 --cors-configuration file://CORS.json
    CORS.jsonの内容に不備があるとエラーが帰ってきます。正常にいけば何も帰ってきません。
    Amazon S3のコンソール画面でCORSの設定画面を見ると、先ほど作成したCORSの設定が反映されていることがわかります。
    Amazon S3 CORS設定

    それでもうまくいかない…

    Umm...
    実際にリッチテキストエディターで画像を投稿すると、画像だけ無視されて投稿されてしまいます。
    画像だけで投稿しようとするとバリデーションエラーが発生します。
    ログでは正常にS3にアップロードされているように見えるんですが…
    Started POST "/rails/active_storage/direct_uploads" for ::1 at 2019-09-07 00:07:12 +0900
    Processing by ActiveStorage::DirectUploadsController#create as JSON
      Parameters: {"blob"=>{"filename"=>"759647.jpg", "content_type"=>"image/jpeg", "byte_size"=>1124951, "checksum"=>"aNJX53d715bfIlPCp+kxng=="}, "direct_upload"=>{"blob"=>{"filename"=>"759647.jpg", "content_type"=>"image/jpeg", "byte_size"=>1124951, "checksum"=>"aNJX53d715bfIlPCp+kxng=="}}}
       (0.1ms)  begin transaction
      ActiveStorage::Blob Create (2.8ms)  INSERT INTO "active_storage_blobs" ("key", "filename", "content_type", "byte_size", "checksum", "created_at") VALUES (?, ?, ?, ?, ?, ?)  [["key", "xtyzr6n5dqtkrtktaw4eyff6cqx7"], ["filename", "759647.jpg"], ["content_type", "image/jpeg"], ["byte_size", 1124951], ["checksum", "aNJX53d715bfIlPCp+kxng=="], ["created_at", "2019-09-07 00:07:13.831165"]]
       (1.9ms)  commit transaction
      S3 Storage (1.9ms) Generated URL for file at key: xtyzr6n5dqtkrtktaw4eyff6cqx7 (https://バケット名.s3.ap-northeast-1.amazonaws.com/xtyzr6n5dqtkrtktaw4eyff6cqx7?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIASDZCAGFGPBO5QBPX%2F20190906%2Fap-northeast-1%2Fs3%2Faws4_request&X-Amz-Date=20190906T150713Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-md5%3Bcontent-type%3Bhost&X-Amz-Signature=759db267c76e158c753e0ccff9a9f488251f83a36d880395005a45b1a8a05613)
    Completed 200 OK in 993ms (Views: 0.5ms | ActiveRecord: 6.1ms | Allocations: 140789)

    追記

    config/application.rb
    require 'rails/all'
    require 'active_storage'

    Gemfile
    gem 'aws-sdk-s3', require: false

    関連記事

    関連記事はありません。