環境
ruby2.6.5
rails5.2.4
gem 'carrierwave'
gem 'fog-aws'
##ステップ1 日本語のファイル名をやめよう
投稿されたファイル名に日本語が含まれている場合、その後の処理が難しくなります。gem 'carrierwave'では、公式にもある通り、ファイル名を変更することができますので、まずそこから始めましょう。
私の場合は、ファイル名をランダム英数字で保存することにしました。保存する時に現在時刻を使用するのはやめましょう。リサイズする時に時刻がずれてしまい、エラーがおきます。
def filename
"#{secure_token}.#{file.extension}" if original_filename.present?
end
def secure_token
var = :"@#{mounted_as}_secure_token"
model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid)
end
このように記述することで投稿されたファイル名はランダム英数字で保存されます。filenameのみでは、ファイル名は変更されるものの、S3へのアクセスがうまくいきませんでしたが、def secure_tokenを追加で記述することにより解決されました。
##ステップ2 ルーティングを設定
resources :posts do
member do
get :download
end
end
##ステップ3 controllerにダウンロードメソッドを記述しよう
def download
url = URI.encode(@post.image.url)
data_path = open(url)
send_data data_path.read, disposition: 'attachment',
type: @post.image_type
end
私のレベルは初学者レベルなので記述に無駄はあると思いますがご容赦ください。
遭遇したエラーと解決まで
最初にファイル名に日本語名が含まれていた時には、アップロードする分には何も問題はありませんでした。しかし、いざダウンロードメソッドを記述してダウンロードしようとすると、502 access deniedが表示されました。この502が厄介で、最初はAWSへのアクセス権限がないのかと思いましたが、アップロードできているのならば、アクセス権限はあるはずです。さらに調べていくと、URLが見つからない場合も502が表示されることがわかり,
さらに日本語表記が原因であることがわかりました。画像投稿サイトでもダウンロードする際には、ランダム英数字のファイルになっていることが多かったのは、このような理由だったのでしょう。