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

Rails 7中Paperclip文件大小与类型验证失效问题求助

Rails 7 + Ruby 3 下 Paperclip 6.1 附件验证失效问题解决

问题描述

将基于 Rails 3、Ruby 1.9.3 的旧系统升级至 Rails 7.1.3.2、Ruby 3.3.0 后,沿用 Paperclip 6.1 处理附件,但原有的文件类型与大小验证全部失效,具体表现为:

  • 上传合法PDF文件时触发错误;
  • 上传PNG、Excel、Zip等非允许类型文件时触发错误;
  • 上传符合类型但超出2MB的文件时触发错误。

现有代码

模型代码

class User < ApplicationRecord
  base_url = "\/home\/muhammadans41\/Downloads\/paperclip\/comments\/:id\/:style\/:basename.:extension"
  base_path = "\/home\/muhammadans41\/Downloads\/paperclip\/comments\/:id\/:style\/:basename.:extension"
  has_attached_file :avatar, storage: :filesystem, styles: { small: "264x204>", large: "800x800>"}, path: "#{base_path}", url: "#{base_url}"
  validates_attachment_content_type :avatar, content_type: ["image\/jpeg", "image\/jpg", "application\/pdf"]
  validates_attachment_size :avatar, :less_than => 2.megabytes
end

Schema 代码

create_table "users", force: :cascade do |t|
  t.string "username"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.string "avatar_file_name"
  t.integer "avatar_file_size"
  t.string "avatar_content_type"
  t.datetime "avatar_updated_at"
end

表单代码

<%= form_with(model: user) do |form| %>
  <% if user.errors.any? %>
    <div style="color: red">
      <h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>
      <ul>
        <% user.errors.each do |error| %>
          <li><%= error.full_message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>
  <div>
    <%= form.label :username, style: "display: block" %>
    <%= form.text_field :username %>
  </div>
   <div>
    <%= form.file_field :avatar %>
  </div>
  <div>
    <%= form.submit %>
  </div>
<% end %>

控制器代码

class UsersController < ApplicationController
  before_action :set_user, only: %i[ show edit update destroy ]

  # GET /users or /users.json
  def index
    @users = User.all
  end

  # GET /users/1 or /users/1.json
  def show
  end

  # GET /users/new
  def new
    @user = User.new
  end

  # GET /users/1/edit
  def edit
  end

  # POST /users or /users.json
  def create
    @user = User.new(user_params)

    respond_to do |format|
      if @user.save
        format.html { redirect_to user_url(@user), notice: "User was successfully created." }
        format.json { render :show, status: :created, location: @user }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /users/1 or /users/1.json
  def update
    respond_to do |format|
      if @user.update(user_params)
        format.html { redirect_to user_url(@user), notice: "User was successfully updated." }
        format.json { render :show, status: :ok, location: @user }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /users/1 or /users/1.json
  def destroy
    @user.destroy!

    respond_to do |format|
      format.html { redirect_to users_url, notice: "User was successfully destroyed." }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_user
      @user = User.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def user_params
      params.require(:user).permit(:username, :avatar)
    end
end

问题原因与修复方案

1. 解决 Turbo 兼容性问题

Rails 7 中 form_with 默认启用 Turbo,但 Paperclip 6.1 对 Turbo 文件上传的支持不完善,会导致参数解析异常,进而影响验证逻辑。

  • 修改表单,添加 local: true 禁用 Turbo:
    <%= form_with(model: user, local: true) do |form| %>
    

2. 修正内容类型验证

原代码中 content_type 数组使用了不必要的转义符,且新版环境下可能需要绕过 MIME 类型的自动检测:

  • 更新模型中的验证代码:
    validates_attachment_content_type :avatar, 
      content_type: ["image/jpeg", "image/jpg", "application/pdf"],
      validate_media_type: false
    

3. 修正路径配置

原路径中的转义符在 Ruby 3 下可能导致路径解析错误,去掉转义符:

base_url = '/home/muhammadans41/Downloads/paperclip/comments/:id/:style/:basename.:extension'
base_path = '/home/muhammadans41/Downloads/paperclip/comments/:id/:style/:basename.:extension'

4. 确保文件大小验证正常

如果 Turbo 禁用后大小验证仍有问题,可直接使用数值替代 2.megabytes:

validates_attachment_size :avatar, less_than: 2 * 1024 * 1024 # 2MB

5. 补充兼容性补丁

添加 paperclip-rails gem 修复 Paperclip 在 Rails 7 下的适配问题:

  • 在 Gemfile 中添加:
    gem 'paperclip-rails'
    
  • 执行 bundle install

验证修复效果

完成修改后重新测试三种场景:

  • 上传合法PDF文件,应成功保存;
  • 上传PNG等非允许类型文件,应触发内容类型错误;
  • 上传超过2MB的合法文件,应触发文件大小错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 22:29:50