URI::InvalidURIError(错误的URI(不是URI吗?):nil)Active Storage serv



配置信息

rails version 6.0
ruby version 2.7.0
gem 'image_processing', '~> 1.2'

存储.yml

local:
service: Disk
root: <%= Rails.root.join("storage") %>

开发.rb

config.active_storage.service = :local
Rails.application.routes.default_url_options[:host] = 'localhost:3000'
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

只有当我使用service= :local时才会出现此异常使用AWS S3配置,在使用:amazon时效果良好。

user.rb型号

has_one_attached :avatar

#throwing exception
def avatar_urls
{
original: avatar.service_url
} if avatar.attachment
end

访问avatar_urls时抛出异常(URI::InvalidURIError (bad URI(is not URI?): nil)(。然而,就像我把avatars_url方法改为following一样,它工作得很好。

#working method
def avatar_urls
{
thumbnail: url_for(avatar.variant(resize: "100x100").processed)
} if avatar.attachment
end

这是跟踪:

Disk Storage (5056.7ms) Generated URL for file at key: variants/i5w1ie6ro07mib4qcdn30lmik6wn/2a7fa5dad6ac227a16e961cbd12ca6f35f1d7947f56a97754d5e22c1a0fd3372 ()
cb_app_container | Completed 500 Internal Server Error in 9523ms (ActiveRecord: 580.9ms | Allocations: 1185509)
cb_app_container | URI::InvalidURIError (bad URI(is not URI?): nil):
cb_app_container | app/models/user.rb:53:in `avatar_urls'
cb_app_container | app/models/user.rb:27:in `user_json'
cb_app_container | app/controllers/api/v1/users_controller.rb:13:in `update'
cb_app_container | [ActiveJob] [ActiveStorage::AnalyzeJob] [33448db4-cf54-4677-906c-06b59f1579ee]    (61.6ms)  BEGIN
cb_app_container | [ActiveJob] [ActiveStorage::AnalyzeJob] [33448db4-cf54-4677-906c-06b59f1579ee]   ActiveStorage::Blob Update (10.3ms)  UPDATE "active_storage_blobs" SET "metadata" = $1 WHERE "active_storage_blobs"."id" = $2  [["metadata", "{"identified":true,"width":1952,"height":3264,"analyzed":true}"], ["id", 45]]
cb_app_container | [ActiveJob] [ActiveStorage::AnalyzeJob] [33448db4-cf54-4677-906c-06b59f1579ee]    (19.6ms)  COMMIT
cb_app_container | [ActiveJob] [ActiveStorage::AnalyzeJob] [33448db4-cf54-4677-906c-06b59f1579ee] Performed ActiveStorage::AnalyzeJob (Job ID: 33448db4-cf54-4677-906c-06b59f1579ee) from Async(default) in 6916.06ms

我在Rails 6.1中遇到了同样的问题,发现我必须在控制器中包含一个特殊的问题,以使ActiveStorage知道当前的主机:

module Api
module V1
class ApiController < ActionController::API
# Make ActiveStorage aware of the current host (used in url helpers)
include ActiveStorage::SetCurrent
end
end
end

我最终在控制器中包含了include Rails.application.routes.url_helpers,并使用了rails_blob_url(avatar.image)。我还在路由文件中加载了这一行。我稍后会重构它。

Rails.application.routes.default_url_options[:host] = 'localhost:3000'

我最终使用了url_for:

Rails.application.routes.url_helpers.url_for(Event.last.image)

对于Rails 5.x上遇到此问题的任何人,都需要为service_url定义主机。这是ActiveStorage使用的代码:https://github.com/rails/rails/blob/v5.2.6/activestorage/app/controllers/active_storage/base_controller.rb

关键行是:ActiveStorage::Current.host = request.base_url

在呼叫avatar.service_url之前坚持

需要注意的是:您可能不想直接调用avatar.service_urlurl_for(...)会自动为您处理所有这些管道。

对我来说,最简单的方法是将其添加到application_controller.rb

# app/controllers/application_controller.rb
include ActiveStorage::SetCurrent

它100%来自@RemonAldenbeuving的答案,只是简单一点。

根据文档https://api.rubyonrails.org/classes/ActiveStorage/Variant.html在processed.service_url:这将创建和处理被限制为高度和宽度为100的化身blob的变体。然后,它将根据blob的派生密钥和转换将所述变体上传到服务

此外:https://api.rubyonrails.org/classes/ActiveStorage/Variant.html#method-i-service_url

查看GH的代码,我可以看到service来自https://github.com/rails/rails/blob/fbe2433be6e052a1acac63c7faf287c52ed3c5ba/activestorage/app/models/active_storage/blob.rb其在这种情况下表示web服务S3。

我认为(因为担心出错和丢分(,你不应该在本地使用它,只应该像你在S3中所说的那样在prod上使用它。磁盘似乎不被视为一种服务(出于明显的原因(,必须深入研究代码(现在只是处理这个问题,如果我设置了<%= image_tag category.image.variant(resize_to_fill: [400, 400]) %>,但在本地主机上的<%= image_tag category.image.variant(resize_to_fill: [400, 400]).processed.service %>上失败了,它就可以工作,但我可以访问.processed,只是.service失败了(。

你还做了什么让它在本地工作吗?我想你也可以添加一个条件来检查它运行的环境。

获取url的更好方法如下所示:https://stackoverflow.com/a/53547638

Rails.application.routes.url_helpers.rails_representation_url(picture_of_car.variant(resize: "300x300").processed, only_path: true)

最新更新