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

Rails 7 ActiveStorage从URL传图遇FileNotFoundError求助

Rails 7 ActiveStorage FileNotFoundError 排查与解决

问题分析

你遇到的ActiveStorage::FileNotFoundError,本质是文件上传过程中流处理或类型推断异常,导致实际存储的文件无法被Representation(缩略图生成)功能正确识别。虽然数据库里Blob和Attachment条目存在,但存储服务里的文件可能未正确写入,或者元数据(如content_type)缺失/错误。

第一种方法失败的原因

  1. open方法的潜在问题
    你用open()读取本地文件,若环境中引入了URI模块,open会指向URI.open,当传入本地路径时可能触发错误的解析逻辑;即使是Kernel#open,未指定二进制模式打开文件,也可能导致文件内容被转义,ActiveStorage无法正确写入存储。

  2. content_type自动推断失败
    attach方法依赖从io对象推断文件的content_type,如果源文件的格式无法被自动识别,Blob的content_type字段会是nil或错误值,后续生成Representation时(比如访问redirect URL),ActiveStorage无法找到对应的处理器,最终抛出文件找不到的错误。

  3. 事务回调的延迟问题
    在User的after_create回调中执行创建Mainphoto和attach操作,若整个回调处于User创建的事务中,attach完成后事务未提交,可能导致Blob的元数据未完全同步到存储服务。

第二种方法有效的原因

你手动调用ActiveStorage::Blob.create_and_upload!和ActiveStorage::Attachment.create,相当于绕开了has_one_attached的自动封装:

  • create_and_upload!直接同步完成Blob创建和文件上传,避免了事务延迟问题;
  • 手动指定了content_type: 'image',强制设置了文件元数据,确保Representation功能能正确识别文件类型;
  • 用File.open直接读取本地文件,避免了open方法的不确定性。

解决方案

修改你的代码,解决文件读取和类型推断问题:

Mainphoto.create!(profile_id: self.profile.id)
# 用File.open以二进制模式读取本地文件
file = File.open("#{Rails.root}/public" + self.profile.avatar_photo_url, 'rb')
photo_url = self.profile.avatar_photo_url

self.profile.mainphoto.main_photo.attach(
  io: file,
  filename: photo_url.slice(8..),
  content_type: 'image/jpeg' # 根据实际图片类型调整,比如image/png
)
# 手动关闭文件流
file.close

额外检查点

  1. 确认config/storage.yml的本地存储配置正确:
local:
  service: Disk
  root: <%= Rails.root.join("storage") %>
  1. 检查public目录下的源文件是否存在,且Rails进程有读取权限;
  2. 查看数据库中Blob表的content_type字段,确保第一种方法生成的记录有正确的类型值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 01:01:18