Upload file to S3 using Active Storage
Goal: create an image model and upload images to Amazon S3 using Active Storage with Rails 5.2.
- Run rails new image-lib to create a rails project
- Run rails active_storage:install
- Run rails g model Image description:string to create image model
- Run rails db:migrate to create tables for image model and active storage
- Update Image model to have a file at /app/models/image.rb:
class Image < ApplicationRecord
has_one_attached :file
end
- Run rails g controller image new index create to create Image controller with new, index and create actions
- Update new view with a form at /app/views/image/new.html.erb
<%= form_for :image, :url => {action: "create"} do |f| %>
<p>description: <%= f.text_field :description %></p>
<p>file: <%= f.file_field :file %></p>
<%= f.submit "Create" %>
<% end %>
- Update new and create controller at /app/controllers/image_controller.rb
def new
@image = Image.new
end
def create
data = params.require(:image).permit(:description, :file)
@image = Image.new(data)
respond_to do |format|
if @image.save
format.html { redirect_to image_index_path }
end
end
end
- Update new view at /app/views/image/index.html.erb to display list of images and its description
<h1>Image#index</h1>
<% @images.each do |t| %>
<p><%=t.name %></p>
<% if t.file.attached? %>
<%= image_tag(url_for(t.file)) %>
<% end %>
<% end %>
- Update index controller at /app/controllers/image_controller.rb
<h1>Image#index</h1>
<% @images.each do |t| %>
<p><%=t.description %></p>
<% if t.file.attached? %>
<%= image_tag(url_for(t.file)) %>
<% end %>
<% end %>
Check point: you should be able to upload a file at /image/new and see the image at /image/index. Now you’re able to save the file locally, next step is to upload these images to Amazon S3
Configure storage target to Amazon S3
- Go to config/storage.yml and comment out amazon section
- Update region and bucket name. You can find these information in our Amazon S3 account:
# 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-2**
bucket: **yh-upload-to-s3**
- Add Amazon s3 SDK in your Gemfile, install the gem
gem "aws-sdk-s3", require: false
- Create AWS IAM user that has permissions: s3:ListBucket, s3:PutObject, s3:GetObject, and s3:DeleteObject
- Run EDITOR=VIM rails credentials:edit to decrypted credentials.yml.enc and update access key id and secret access key
- uncomment AWS section, and enter proper access_key_id and secret_access_key for the AWS IAM user
aws:
access_key_id: {your-access-key}
secret_access_key: {your-secret-access-key}
- Change your development storage service to use S3 at /config/environments/development.rb
config.active_storage.service = :amazon
Check point: you should be able to upload a file at /image/new, and these files should upload to your AWS S3 bucket
Useful links: