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

同一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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 09:34:55