Rails Active Storage 2026: Upload File, Tich Hop S3 va Cau Hoi Phong Van

Huong dan chi tiet ve Rails Active Storage de upload file, tich hop Amazon S3 va chuan bi cho phong van Ruby on Rails.

Rails Active Storage 2026: Upload File, Tich Hop S3 va Cau Hoi Phong Van

Active Storage la tinh nang tich hop san trong Ruby on Rails giup don gian hoa qua trinh upload file va quan ly attachment. Voi su ho tro cac dich vu luu tru dam may nhu Amazon S3, Google Cloud Storage va Microsoft Azure, Active Storage cung cap giai phap toan dien cho cac nhu cau xu ly file trong ung dung web hien dai.

Bai viet nay se huong dan cach trien khai upload file voi Active Storage, cau hinh tich hop S3, va chuan bi cho cac cau hoi phong van lien quan den xu ly file trong Ruby on Rails.

Active Storage da tro thanh tieu chuan cho xu ly file trong Rails tu phien ban 5.2. Hieu ro tinh nang nay la dieu can thiet cho moi developer Rails muon xay dung ung dung san sang cho production.

Hieu Ve Kien Truc Active Storage

Active Storage su dung hai bang co so du lieu de quan ly attachment: active_storage_blobs va active_storage_attachments. Bang blob luu tru metadata file nhu ten, content type va checksum, trong khi bang attachment ket noi blob voi model ActiveRecord.

Kien truc nay cho phep mot file duoc attach vao nhieu record va ho tro nhieu storage backend khac nhau ma khong can thay doi code ung dung.

bash
# Generate Active Storage tables
rails active_storage:install
rails db:migrate

Cac lenh tren tao migration cho hai bang ma Active Storage can thiet.

Cau Hinh Model De Upload File

Them attachment vao model Rails rat don gian voi cac macro has_one_attached va has_many_attached.

ruby
# app/models/user.rb
class User < ApplicationRecord
  has_one_attached :avatar
  has_many_attached :documents

  validates :avatar, content_type: ['image/png', 'image/jpeg'],
                     size: { less_than: 5.megabytes }
end

Voi khai bao nay, model User co the nhan mot avatar va nhieu documents.

Trien Khai Controller De Upload

Controller xu ly qua trinh upload bang cach su dung strong parameters de nhan file tu form.

ruby
# app/controllers/users_controller.rb
class UsersController < ApplicationController
  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to @user, notice: 'User created successfully'
    else
      render :new, status: :unprocessable_entity
    end
  end

  def update
    @user = User.find(params[:id])
    if @user.update(user_params)
      redirect_to @user, notice: 'User updated successfully'
    else
      render :edit, status: :unprocessable_entity
    end
  end

  private

  def user_params
    params.require(:user).permit(:name, :email, :avatar, documents: [])
  end
end

Tao Form Upload Voi Rails 8

Rails 8 cung cap form helper tich hop voi Active Storage.

erb
<%# app/views/users/_form.html.erb %>
<%= form_with model: @user do |form| %>
  <div class="field">
    <%= form.label :avatar %>
    <%= form.file_field :avatar, accept: 'image/png,image/jpeg',
        direct_upload: true %>
  </div>

  <div class="field">
    <%= form.label :documents %>
    <%= form.file_field :documents, multiple: true,
        direct_upload: true %>
  </div>

  <%= form.submit %>
<% end %>

Thuoc tinh direct_upload: true cho phep upload truc tiep den storage service ma khong qua server Rails.

Cau Hinh Amazon S3 Cho Production

Doi voi moi truong production, S3 la lua chon pho bien nho kha nang mo rong va do tin cay.

yaml
# config/storage.yml
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: ap-southeast-1
  bucket: myapp-production-uploads
  public: false

Cau hinh tren su dung Rails credentials de luu tru API keys mot cach an toan.

ruby
# config/environments/production.rb
Rails.application.configure do
  config.active_storage.service = :amazon
end

Them Cac Gem Can Thiet

S3 storage yeu cau gem AWS SDK.

ruby
# Gemfile
gem 'aws-sdk-s3', require: false
gem 'image_processing', '~> 1.2'

Gem image_processing can thiet cho cac tinh nang variant nhu resize va crop hinh anh.

Image Variants Va Bien Doi

Active Storage cung cap tinh nang variant de thay doi kich thuoc va dinh dang hinh anh theo yeu cau.

ruby
# Generating image variants
@user.avatar.variant(resize_to_limit: [200, 200]).processed

# Pre-defined variants in model
class User < ApplicationRecord
  has_one_attached :avatar do |attachable|
    attachable.variant :thumb, resize_to_limit: [100, 100]
    attachable.variant :medium, resize_to_limit: [300, 300]
    attachable.variant :large, resize_to_limit: [800, 800]
  end
end

Variant duoc tao theo kieu lazy va duoc cache cho cac request tiep theo.

Hien Thi Attachment Trong View

Rails cung cap helper de hien thi hinh anh va file attachment.

erb
<%# Display avatar with variant %>
<%= image_tag @user.avatar.variant(:thumb) if @user.avatar.attached? %>

<%# Link to download document %>
<% @user.documents.each do |document| %>
  <%= link_to document.filename, rails_blob_path(document, disposition: 'attachment') %>
<% end %>

<%# Display image with fallback %>
<%= image_tag(@user.avatar.attached? ? @user.avatar.variant(:medium) : 'default-avatar.png') %>

Direct Upload Voi JavaScript

Direct upload cho phep file duoc gui truc tiep den storage service, giam tai cho server Rails.

app/javascript/direct_uploads.jsjavascript
import { DirectUpload } from "@rails/activestorage"

class DirectUploadController {
  constructor(file, url) {
    this.directUpload = new DirectUpload(file, url, this)
  }

  upload() {
    return new Promise((resolve, reject) => {
      this.directUpload.create((error, blob) => {
        if (error) {
          reject(error)
        } else {
          resolve(blob.signed_id)
        }
      })
    })
  }

  directUploadWillStoreFileWithXHR(request) {
    request.upload.addEventListener("progress", event => {
      const progress = (event.loaded / event.total) * 100
      console.log(`Upload progress: ${progress.toFixed(2)}%`)
    })
  }
}

export { DirectUploadController }

Xac Thuc File Voi Custom Validator

Xac thuc phuc tap hon co the duoc trien khai voi custom validator.

ruby
# app/validators/file_size_validator.rb
class FileSizeValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    return unless value.attached?

    if value.is_a?(ActiveStorage::Attached::Many)
      value.each do |attachment|
        validate_attachment(record, attribute, attachment)
      end
    else
      validate_attachment(record, attribute, value)
    end
  end

  private

  def validate_attachment(record, attribute, attachment)
    max_size = options[:max] || 10.megabytes
    if attachment.blob.byte_size > max_size
      record.errors.add(attribute, "is too large (max: #{max_size / 1.megabyte}MB)")
    end
  end
end

Xu Ly Background Voi Active Job

Cac tac vu nang nhu video transcoding nen duoc thuc hien o background.

ruby
# app/jobs/process_video_job.rb
class ProcessVideoJob < ApplicationJob
  queue_as :default

  def perform(video_id)
    video = Video.find(video_id)
    return unless video.file.attached?

    video.file.analyze
    # Additional processing logic
  end
end

# Trigger job after upload
class Video < ApplicationRecord
  has_one_attached :file

  after_commit :process_video, on: [:create, :update]

  private

  def process_video
    ProcessVideoJob.perform_later(id) if file.attached?
  end
end

Testing Active Storage

Rails cung cap fixtures va helpers de test Active Storage.

ruby
# test/models/user_test.rb
require 'test_helper'

class UserTest < ActiveSupport::TestCase
  test 'should attach avatar' do
    user = users(:john)
    user.avatar.attach(
      io: File.open(Rails.root.join('test/fixtures/files/avatar.png')),
      filename: 'avatar.png',
      content_type: 'image/png'
    )

    assert user.avatar.attached?
    assert_equal 'avatar.png', user.avatar.filename.to_s
  end

  test 'should validate avatar content type' do
    user = users(:john)
    user.avatar.attach(
      io: File.open(Rails.root.join('test/fixtures/files/document.pdf')),
      filename: 'document.pdf',
      content_type: 'application/pdf'
    )

    assert_not user.valid?
    assert_includes user.errors[:avatar], 'has an invalid content type'
  end
end

Cac Cau Hoi Phong Van Ve Active Storage

Duoi day la nhung cau hoi thuong gap trong phong van Ruby on Rails:

Su khac biet giua has_one_attached va has_many_attached la gi?

has_one_attached dung cho single file attachment nhu avatar, trong khi has_many_attached dung cho nhieu file nhu gallery hoac documents.

Active Storage luu tru file mac dinh nhu the nao?

Mac dinh, Active Storage su dung disk service luu tru file trong thu muc storage/ cua ung dung. Doi voi production, nen su dung cloud storage nhu S3.

Direct Upload la gi va khi nao nen su dung?

Direct Upload cho phep trinh duyet upload file truc tiep den storage service ma khong qua server Rails. Day la giai phap huu ich cho file lon vi giam su dung bo nho tren server.

Lam the nao de toi uu hoa hinh anh voi Active Storage?

Su dung variants de tao cac phien ban hinh anh voi kich thuoc khac nhau. Variants duoc tao theo kieu lazy va duoc cache, nen khong gay tai cho server.

Lam the nao de xoa cac attachment khong su dung?

Su dung task rails active_storage:purge:unattached de don dep cac blob khong ket noi voi bat ky record nao.

ruby
# Manual purge
ActiveStorage::Blob.unattached.where('created_at < ?', 1.day.ago).find_each(&:purge_later)

Sẵn sàng chinh phục phỏng vấn Ruby on Rails?

Luyện tập với mô phỏng tương tác, flashcards và bài kiểm tra kỹ thuật.

Ket Luan

Active Storage cung cap giai phap toan dien cho xu ly file trong Ruby on Rails. Voi tich hop cloud storage nhu S3, tinh nang direct upload va image variants, cac developer co the xay dung he thong upload file co kha nang mo rong va san sang cho production.

Hieu cac khai niem co ban nhu blob, attachment va variants la dieu quan trong cho phong van va phat trien hang ngay. Cac phuong phap tot nhat nhu xac thuc file, xu ly background va testing dung cach se dam bao mot trien khai manh me va de bao tri.

Thử thách hôm nay

Bạn có tìm ra lỗi trong Ruby on Rails không?

Một đoạn mã thật, một lỗi ẩn, mỗi ngày một lượt. Không cần tài khoản để thử.

Anthony Fillion-Maillet

Viết bởi

Anthony Fillion-Maillet

Người sáng lập SharpSkill

Lập trình viên fullstack hơn 10 năm. Anh điều hành SharpSkill và chịu trách nhiệm về mọi nội dung đăng tại đây.

Cập nhật ngày 9 tháng 9, 2026

Chia sẻ

Bài viết liên quan