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

Rails中Pins Controller上传图片重复问题的解决请求

Rails图片重复上传问题排查与解决

问题根源

你的代码中重复执行了图片附加操作,导致每张上传的图片被添加两次:

  • 在create方法里,current_user.pins.build(pin_params)会通过pin_params中的images: []自动附加所有上传的图片,后续又手动遍历params[:pin][:images]再次执行attach操作,造成重复。
  • update方法同理,先执行@pin.update(pin_params)完成图片添加,后续循环又重复附加了一次。

修复方案

第一步:修改参数过滤规则

先调整pin_params,移除自动处理图片的配置,改为手动控制图片附加:

private

def pin_params
  params.require(:pin).permit(:title, :description) # 移除images: [],避免自动附加图片
end

第二步:修正Create方法

保留你的去重逻辑,但只通过手动流程附加图片:

def create
  @pin = current_user.pins.build(pin_params)

  # 处理图片上传并去重
  if params[:pin][:images].present?
    params[:pin][:images].each do |image|
      if image.is_a?(ActionDispatch::Http::UploadedFile)
        image_content = image.read
        checksum = Digest::SHA256.hexdigest(image_content)
        # 检查当前pin是否已存在该图片
        unless @pin.images.any? { |img| img.blob.checksum == checksum }
          @pin.images.attach(io: StringIO.new(image_content), filename: image.original_filename, content_type: image.content_type)
        end
      end
    end
  else
    flash.now[:alert] = "请至少上传一张图片。"
    render :new and return
  end

  respond_to do |format|
    if @pin.save
      format.html { redirect_to @pin, notice: "Pin 创建成功。" }
      format.json { render :show, status: :created, location: @pin }
    else
      format.html { render :new, status: :unprocessable_entity }
      format.json { render json: @pin.errors, status: :unprocessable_entity }
    end
  end
end

第三步:修正Update方法

同样先更新非图片字段,再手动处理新上传的图片去重:

def update
  if @pin.user == current_user
    # 先更新标题、描述等非图片字段
    if @pin.update(pin_params)
      # 处理新上传的图片并去重
      if params[:pin][:images].present?
        params[:pin][:images].each do |image|
          if image.is_a?(ActionDispatch::Http::UploadedFile)
            image_content = image.read
            checksum = Digest::SHA256.hexdigest(image_content)
            unless @pin.images.any? { |img| img.blob.checksum == checksum }
              @pin.images.attach(io: StringIO.new(image_content), filename: image.original_filename, content_type: image.content_type)
            end
          end
        end
      end
      redirect_to @pin, notice: "Pin 更新成功。"
    else
      render :edit, status: :unprocessable_entity
    end
  else
    render :edit, status: :unprocessable_entity
  end
end

逻辑说明

修改后,图片完全由手动流程处理:

  1. 先创建/更新Pin的基础字段(标题、描述)
  2. 遍历上传的图片,通过SHA256校验和判断是否已存在于当前Pin中
  3. 仅附加未存在的图片,既解决了重复上传问题,又保留了你原本想要的去重需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 16:20:53