12/08/2018, 14:38

[RoR] Lưu trữ file trên Amazon S3

Ngày nay, việc sử dụng các dịch vụ "điện toán đám mây" đã trở nên cực kì phổ biến. Từ cá nhân đến các tổ chức doanh nghiệp ở mọi quy mô đều có thể sử dụng hiệu quả các dịch vụ này. Theo định nghĩa của IBM thì: Điện toán đám mây có thể được định nghĩa một cách đơn giản như là sự sử dụng ...

Ngày nay, việc sử dụng các dịch vụ "điện toán đám mây" đã trở nên cực kì phổ biến. Từ cá nhân đến các tổ chức doanh nghiệp ở mọi quy mô đều có thể sử dụng hiệu quả các dịch vụ này. Theo định nghĩa của IBM thì:

Điện toán đám mây có thể được định nghĩa một cách đơn giản như là sự sử dụng tài nguyên tính toán có khả năng thay đổi theo nhu cầu được cung cấp như là một dịch vụ từ bên ngoài với chi phí trả cho mỗi lần sử dụng. Bạn có thể truy cập đến bất kỳ tài nguyên nào tồn tại trong "đám mây (cloud)" tại bất kỳ thời điểm nào và từ bất kỳ đâu thông qua hệ thống Internet. Bạn không phải quan tâm xem làm cách nào các thứ đang được duy trì phía trong của đám mây. Điện toán đám mây cũng có thể được gọi là tính toán tiện ích hay là tính toán lưới (grid computing)

Một trong những nhà cung cấp nổi bật nhất trong lĩnh vực điện toán đám mây đó là Amazon. Trong đó thì Amazon Web Services là tập hợp các dịch vụ cung cấp cho người lập trình có khả năng truy cập tới hạ tầng kiến trúc tính toán kiểu ready-to-use (nôm na là các dịch vụ) của Amazon như lưu trữ, tính toán, truyền thông điệp và tập dữ liệu...

Trong bài viết này, mình xin giới thiệu về dịch vụ lưu trữ đơn giản của Amazon, Amazon Simple Storage Service (S3) cũng như việc thiết lập và cấu hình sử dụng dịch vụ này trong ứng dụng Rails.

Giới thiệu dịch vụ Amazon Simple Storage Service

S3 là hệ thống lưu trữ dữ liệu nhanh và dễ dàng mở rộng, có thể được truy cập từ bất cứ đâu và bất cứ lúc nào thông qua internet. Bạn trả phí dựa trên dung lượng lưu trữ và băng thông mà bạn dùng. Không phí cài đặt, không phí tối thiểu hay phí phụ trội. Bạn có thể tương tác với Amazon S3 thông qua giao diện web sử dụng AWS Management Console.

Đăng ký sử dụng dịch vụ

Để sử dụng được dịch vụ S3, ta follow theo các steps như sau: 1. Đăng ký AWS account

  • Vào đây và chọn nút Create an AWS account
  • Tiếp tục các bước đăng ký account, nhập password và điền các thông tin cá nhân. Sau khi đăng ký thành công, 1 email xác nhận thành công sẽ được gửi tới

2. Tạo bucket mới

  • Mỗi đối tượng được lưu trữ trong Amazon S3 đều được chứa trong một bucket . Bucket có thể được hiểu như là một folder trên hệ thống tệp. Điểm mấu chốt để phân biệt giữa folder và bucket là mỗi thùng và các nội dung của nó có thể truy cập được thông qua URL. Ví dụ, nếu bạn có một bucket tên là buffet, nó có thể truy cập được thông qua URL http://buffet.s3.amazonaws.com.

  • Trên giao diện AWS Management Console, tìm kiếm dịch vụ S3

  • Tại giao diện bucket management, chọn create bucket

3. Config bucket

  • Sau khi tạo xong, chọn bucket vừa tạo -> chọn property -> chọn permission -> Edit CORS Configuration

  • Chỉnh sửa file này như sau để cho phép request từ bên ngoài có thể access tài nguyên trên s3

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>HEAD</AllowedMethod>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>DELETE</AllowedMethod>
        <ExposeHeader>ETag</ExposeHeader>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

Cấu hình connect tới dịch vụ s3 trong ứng dụng rails

  1. Thêm gem trong Gemfile
gem 'aws-sdk', '2.1.36'
gem 'aws-sdk-rails', '1.0.1'
  1. Lưu cặp key aws_access_key_id và aws_secret_access_key, tên bucket, tên region trong secret.yml
  • Cặp key này có thể lấy tại: My Security Credential -> Access Keys
development: &development
  aws_access_key_id: your_aws_access_key_id
  aws_secret_access_key: your_aws_secret_access_key
  s3_bucket: your_bucket_name
  s3_region: 'us-east-1' # với case của mình chỉ chạy với region us-east-1, chưa rõ nguyên nhân vì sao
  1. Tạo project mới
  • Tạo model: UploadFile (id, filename)
class UploadFile < ActiveRecord::Base
end
  • Tạo controller: UploadFilesController#create xử lý việc upload file
class UploadFilesController < ApplicationController
  def create
  end
end
  • Các thành phần khác như views, static_pages,..
  1. Tạo form upload
  • Trong view, tạo form upload file
<%= form_for @upload_file, url: upload_files_path, multipart: true do |f| %>
  <label>Select upload file</label>
  <%= f.file_field :filename %>
  <br>
  <%= f.submit 'Upload' %>
<% end %>
  1. Handle upload file to s3
  • Tạo module AwsResource mục đích để connect tới các service của Amazon
module AwsResource
  class << self
    def for(aws_service, options = {})
      aws_service::Resource.new(
        options.merge(
          access_key_id: Rails.application.secrets.aws_access_key_id,
          secret_access_key: Rails.application.secrets.aws_secret_access_key
      ))
    end
  end
end
  • Handle upload trong controller:
class UploadFilesController < ApplicationController
  def create
    upload_file_to_s3(params[:upload_file][:filename])
    redirect_to root_url
  end

  private
  def s3_bucket
    s3 = AwsResource.for(Aws::S3, region: Rails.application.secrets.s3_region) # connect tới service S3
    s3.bucket(Rails.application.secrets.s3_bucket) # connect tới bucket đã tạo trên S3
  end

  def upload_file_to_s3(upload_file)
    attachment_info = {
      filename: upload_file.original_filename,
      filepath: "upload_files/#{upload_file.original_filename}", # relative_path trên S3
      filesize: upload_file.size
    }
    decode_filedata = upload_file.read # binary data 
    upload(attachment_info[:filepath], decode_filedata)
  end

  def upload(filepath, decode_filedata)
    obj = s3_bucket.object(filepath)
    file_data = {
      body: decode_filedata,
      server_side_encryption: 'AES256',
      expires: Time.zone.now.since(15.minute),
      content_type: 'application/octet-stream',
      acl: 'public-read' # Access Control List, ở đây set public-read có nghĩa là file được up lên sẽ public trên môi trường internet, bất cứ ai có thể "nhìn thấy" file này
    }
    obj.put(file_data)
  end
end

Demo

Link demo

Trên đây mình đã trình bày sơ qua về dịch lưu trữ file đơn giản Amazon Simple Storage Service, cách cấu hình và tích hợp trong ứng dụng rails. Hi vọng bài viết phần nào giúp đỡ các bạn mới và sẽ làm quen với các dịch vụ của Amazon.

Nguồn tham khảo

  1. IBM
  2. Amazon
  3. Gem Aws SDK Rails
  4. AWS For Ruby Doc

Source code

  • https://github.com/duyth93/upload-file-to-s3
0