You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Active Storage 结合 Amazon S3 上传异常:文件以Key而非原文件名存储

Fixing Active Storage's Random Filename Issue on Amazon S3

Hey Andrew, let’s break down why this is happening and how to fix it—this is actually expected default behavior from Active Storage, not a bug in Rails 5 or misconfiguration on Amazon S3.

Why Files Are Stored with Random Keys

Active Storage uses unique, random keys (like 5YE1aJQuFYyWNr6BSHxhQ48t) instead of original filenames for two key reasons:

  • Prevent filename conflicts: If two users upload files with the same name (e.g., myfile.zip), the later upload won’t overwrite the earlier one.
  • Boost security: It stops attackers from guessing filenames to access sensitive files they shouldn’t have permission to view.

Solution 1: Customize Storage Keys to Preserve Original Filenames

If you want the actual filename to appear in your S3 bucket (while still avoiding conflicts), you can define a custom key generator in your config/storage.yml file.

Here’s a sample S3 configuration with a custom key structure:

s3:
  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-bucket-name
  # Custom key that includes a random UUID + original filename to avoid conflicts
  key: <%= ->(blob) { "uploads/#{SecureRandom.uuid}/#{blob.filename}" } %>

This will store files in S3 with paths like uploads/abc123xyz/myfile.zip—the random UUID ensures uniqueness, while the original filename is preserved at the end.

You can tweak the structure further (e.g., organize files by user ID):

key: <%= ->(blob) { "users/#{blob.record.id}/#{SecureRandom.uuid}/#{blob.filename}" } %>

Note: Active Storage’s filename attribute automatically sanitizes invalid characters (like spaces or special symbols) to comply with S3’s naming rules.

Solution 2: Keep Random Storage Keys, Show Original Filename on Download

If you don’t care about the filename in S3 but want users to download files with their original names, you don’t need to change storage settings. Instead, adjust your controller to set the download filename.

Here’s a sample controller action:

def download
  blob = ActiveStorage::Blob.find(params[:id])
  send_data blob.download, 
            filename: blob.filename.to_s,
            type: blob.content_type,
            disposition: "attachment"
end

When users hit this endpoint, their browser will receive the file with its original name (e.g., myfile.zip) even though it’s stored as a random key in S3.

Quick Sanity Checks

  • Confirm your storage.yml is linked correctly in your environment config (e.g., config/environments/production.rb):
    config.active_storage.service = :s3
    
  • Verify your S3 bucket has proper write permissions for Active Storage (this doesn’t affect filename handling, but ensures uploads work at all).

内容的提问来源于stack exchange,提问作者Drew Potter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:57:48