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

Rails Action Text临时附件残留:如何清理数据库与磁盘文件?

解决Active Text未提交表单时的废弃文件清理问题

核心原因

Active Text依赖的Trix编辑器默认采用即时上传机制,图片一上传到编辑器就会写入Active Storage,生成对应的active_storage_blobs记录并存储文件,这个流程和表单是否提交完全无关,所以取消表单后会留下无主的文件和数据库记录。

解决方案

1. 定时清理无主文件

Rails 6及以上版本的Active Storage提供了unattached scope,可以直接筛选未关联任何业务模型的Blob,配合定时任务定期清理:

# 清理24小时前创建的无主Blob(同时删除数据库记录和磁盘文件)
ActiveStorage::Blob.unattached.where("created_at < ?", 24.hours.ago).find_each(&:purge_later)
  • 用purge_later异步执行,避免阻塞主线程,适合大量文件的场景;如果需要同步清理,改用purge方法。
  • 可以借助Sidekiq Cron、Whenever等工具,把这段逻辑配置成每日/每小时执行的定时任务。

2. 表单取消时主动清理

通过前端捕获取消事件,主动请求后端清理当前表单关联的临时文件:

  • 前端逻辑(JavaScript):
    // 给取消按钮绑定事件
    document.getElementById('cancel-btn').addEventListener('click', async () => {
      const tempToken = document.querySelector('[name="form_temp_token"]').value;
      await fetch('/cleanup_temp_blobs', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content
        },
        body: JSON.stringify({ temp_token: tempToken })
      });
    });
    
  • 后端逻辑(控制器):
    # 新增清理临时文件的action
    def cleanup_temp_blobs
      temp_token = params[:temp_token]
      # 假设上传时把临时标识存在Blob的metadata里
      ActiveStorage::Blob.where("metadata @> ?", { temp_token: temp_token }.to_json).find_each(&:purge_later)
      head :ok
    end
    
  • 路由配置:
    # routes.rb
    post '/cleanup_temp_blobs', to: 'forms#cleanup_temp_blobs'
    
  • 上传时需要给Blob打上临时标识:可以在表单初始化时生成一个唯一token存在会话或隐藏域,上传图片时把这个token写入Blob的metadata字段。

3. 给临时Blob打标记区分

如果需要更精准地区分临时文件和正式文件,可以给active_storage_blobs表新增字段:

# 生成迁移文件
rails generate migration AddIsTempToActiveStorageBlobs is_temp:boolean default:false
rails db:migrate

上传图片时标记为临时文件:

# 在上传处理器或控制器中设置
blob.is_temp = true
blob.save

清理时只针对标记为临时的无主Blob:

ActiveStorage::Blob.unattached.where(is_temp: true, created_at: ...).find_each(&:purge_later)

当表单提交成功后,再把对应的Blob标记为非临时:

# 表单提交后的逻辑
@model.body.attachments.each do |attachment|
  attachment.blob.update(is_temp: false)
end

内容的提问来源于stack exchange,提问作者Johan Donado B.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:00:57