我最近一直在尝试实现 Ruby on Rails 的 ActiveStorage。我的设置非常简单,但我在使用
<%= image_tag...
处理我上传的文件时遇到问题。我正在从 AWS S3 中提供文件。这是我的测试设置:
storage.yml
# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
amazon:
service: S3
# Instad of specifying these or using Rails.application.credentials we can rely on env vars or any other valid way of authenticating the aws sdk gem
access_key_id: # Hard coded creds right now for testing
secret_access_key: # Hard coded creds right now for testing
region: us-east-1
bucket: test-my-s3-bucket-name
我一直在使用名为
personnel
的模型进行测试
class Personnel < ApplicationRecord
...
# NEW ACTIVESTORAGE CODE
has_one_attached :as_photo
# OPTIONAL:
validates :as_photo, size: { less_than: 3.megabytes , message: 'is too large' },
content_type: {in: ['image/jpeg', 'image/png', 'image/gif', 'image/pjpeg', 'image/x-png'],
message: I18n.t("errors.file_invalid_format", :formats => "JPG,GIF,PNG") }
before_save :define_attachment_key
# This method will generate a string based on the model name
# This string is used in the file's key name on S3. This is how we place files into s3 "sub folders" for organizational/browsing purposes
def photo_path
# This key has to be unique across all assets which is why we call ActiveRecord::SecureToken.generate_unique_secure_token
# modelname/uuid but you could create further subdivisions if you wanted. modelname/attachment1/uuid & modelname/attachment2/uuid for example
"public/#{Rails.env}/models/#{self.class.name}/photo/#{ActiveStorage::Blob.generate_unique_secure_token}"
end
def define_attachment_key
as_photo.key = photo_path if as_photo.new_record?
# add any additional ..._path methods here if there are multiple attachments on this model you want subfolders for.
# Attachments without a ..._path method will placed at the root of the bucket
end
然后我有一个指向此模板的测试路线
<h1>Personnel</h1>
<h2>There are a total of <%= @count %> Personnel records</h2>
<ul>
<% @persons.each do |person| %>
<li>
<%= person.id %>
<% if person.as_photo.present? %>
<ul>
<li>
<%= image_tag(person.as_photo) %>
</li>
<li>
Proxy: <%= image_tag rails_storage_proxy_path(person.as_photo) %>
</li>
<li>
img tag with as.url: <img src="<%= person.as_photo.url %>" alt="an image wow">
</li>
</ul>
<% end %>
</li>
<% end %>
</ul>
但是正如您所看到的,这 3 种渲染图像的方式中仅显示了一种 我认为不同方法提供的 URL 与此有关。
person.as_photo.url
url 看起来像一个预先签名的 AWS url,而仅使用 person.as_photo
和 image_tag 的其他 2 种方法(如文档使用中的示例)似乎会生成一个以某种方式首先通过 Rails 服务器路由的 URL,这些是那些不起作用的(404)。 http://localhost:3000/rails/active_storage/blobs/proxy
& http://localhost:3000/rails/active_storage/blobs/redirect
明白了。 这个问题帮助我弄清楚了。显然,Activestorage 将其自己的路由附加到主路由文件中。如果您有一条包罗万象/通配符的路线可以捕获
rails/active_storage/...
(就像我所做的那样。get '*path', to: ...
),那么您需要为 rails/active_storage
路线开辟一个例外。