同一Rails模型的两个Active Storage附件:一个正常一个无法上传
问题描述
我有一个Ruby on Rails 7项目,其中包含Chapter模型(chapters.rb),该模型有两个Active Storage附件:video和cover_image。表单中为每个附件设置了文件字段,且已反复核对命名无误。问题在于,我只能上传Quicktime格式的视频,却无法上传jpg格式的封面图。上传视频时,表单可正常提交并快速跳转到详情页,视频也能正常显示。
但尝试上传封面图时,会弹出对话框提示“Error reading [对应文件名]”,JavaScript控制台显示错误:
Failed to load resource: The operation couldn’t be completed. (WebKitBlobResource error 4.)
Rails控制台无任何输出。视频和封面图的配置看起来完全一致且正确,这十分令人困惑,求解决思路?
相关代码
Chapter模型(app/models/chapter.rb)
class Chapter < ApplicationRecord belongs_to :curriculum # has_one :curriculum_video, dependent: :destroy has_many :sections, dependent: :destroy has_one_attached :cover_image has_one_attached :video end
表单视图(app/views/chapters/new.html.erb 或 edit.html.erb)
<%= form_with(model: [@curriculum, @chapter], class: "contents") do |form| %> <% if @chapter.errors.any? %> <div id="error_explanation" class="bg-red-50 text-red-500 px-3 py-2 font-medium rounded-lg mt-3"> <h2><%= pluralize(@chapter.errors.count, "error") %> prohibited this chapter from being saved:</h2> <ul> <% chapter.errors.each do |error| %> <li><%= error.full_message %></li> <% end %> </ul> </div> <% end %> <%= form.hidden_field :curriculum_id %> <div class="my-5"> <%= form.label :title %> <%= form.text_field :title, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full" %> </div> <div class="my-5"> <%= form.label :description %> <%= form.text_field :description, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full" %> </div> <div class="my-5"> <%= form.label :chapter_video %> <%= form.file_field :video, direct_upload: true, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full"%> </div> <div class="my-5"> <%= form.label "Cover Image" %> <%= form.file_field :cover_image, direct_upload: true, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full"%> </div> <div class="inline"> <%= form.submit class: "rounded-lg py-3 px-5 bg-blue-600 text-white inline-block font-medium cursor-pointer" %> </div> <% end %> <script> document.querySelector('.contents').addEventListener('submit', (event) => { console.log('Form submitted!'); }); </script>
Chapters控制器(app/controllers/chapters_controller.rb)
# GET /chapters/1/edit def edit authorize @chapter end # POST /chapters or /chapters.json def create # @chapter = Chapter.new(chapter_params) @chapter = @curriculum.chapters.build(chapter_params) authorize @chapter respond_to do |format| if @chapter.save format.html { redirect_to curriculum_path(@curriculum), notice: "Chapter was successfully created." } format.json { render :show, status: :created, location: @chapter } else format.html { render :new, status: :unprocessable_entity } format.json { render json: @chapter.errors, status: :unprocessable_entity } end end end # PATCH/PUT /chapters/1 or /chapters/1.json def update authorize @chapter respond_to do |format| if @chapter.update(chapter_params) format.html { redirect_to curriculum_chapter_path(@curriculum, @chapter), notice: "Chapter was successfully updated." } format.json { render :show, status: :ok, location: @chapter } else format.html { render :edit, status: :unprocessable_entity } format.json { render json: @chapter.errors, status: :unprocessable_entity } end end end
解决思路
- 检查Active Storage JS依赖:确认
app/javascript/application.js中已引入import "@rails/activestorage"——直接上传功能完全依赖这个模块,缺失会导致图片上传时浏览器无法正确处理Blob资源。 - 移除自定义表单提交监听:页面中的
submit事件监听可能干扰了Active Storage的直接上传流程,暂时注释掉该代码块测试。Active Storage会自动劫持表单提交完成直接上传,自定义监听可能打断这一过程。 - 添加文件类型限制:给封面图的
file_field加上accept: 'image/jpeg,image/png'属性,帮助浏览器过滤非图片文件,同时确保文件类型识别正确:<%= form.file_field :cover_image, direct_upload: true, accept: 'image/jpeg,image/png', class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full"%> - 验证存储目录权限:检查
storage.yml中配置的本地存储路径(默认是Rails.root.join("storage"))是否有Rails进程的读写权限,执行chmod -R 755 storage/修复权限问题。 - 测试非直接上传模式:暂时去掉
direct_upload: true,如果封面图能正常上传,说明问题出在直接上传配置上,可进一步排查Webpack/Importmaps的资源加载情况,或Active Storage的直接上传初始化逻辑。 - 排查文件本身问题:更换其他jpg图片测试,排除图片文件损坏、格式异常(如后缀为jpg但实际是其他格式)的可能。
内容的提问来源于stack exchange,提问作者acoustic_north
相关产品推荐
相关产品推荐

