• bbs1org
    Cloudflare R2 上传
    ID cf_r2版本 1.4.0插件制作者 bbs1org免费1705 行 / 96.7 KBHook / 路由 / 后台页
    附件直存 Cloudflare R2 对象存储,发帖和回帖时支持点击、拖拽、粘贴上传并自动插入链接;可按文件类型设置自动清理服务器上的本地副本,后台可管理上传记录和 R2 文件。
    app/plugins/cf_r2/plugin.php
    开发日志已有 2 条

    此项目接受所有登录用户协助维护和提交更新。

    • qqt123
      qqt123
      版本 1.4.0 c947df6a4821 更新:更新支持删除本地图片,只保留R2的图片。release
    • bbs1org
      bbs1org
      版本 1.0.0 ebe5d4c890ed 更新:第一个版本
    主楼
  • bbs1org

    版本 1.0.0 更新:
    第一个版本

    #1
  • 质量报告

    插件质量报告

    插件:cf_r2

    Hook功能范围循环使用频率文件读写修改系统表读写系统表读写自己的表
    reply.before_save回帖发布/编辑表单提交否3读---
    topic.before_save主题发布/编辑表单提交否3读---
    attachment.uploader主题/回帖编辑表单附件控件否2----
    reply.form_extra回帖编辑表单否2----

    颜色说明:黄色表示有数据读写,红色表示 Hook 在系统循环中执行,浅蓝色表示有文件写入。“列表跳过”表示回调在列表路径会提前返回,“回调内”表示操作位于回调自身或其帮助函数的循环体内。“文件批处理”表示逐个处理用户一次提交的文件,属于必要操作,不标记修正。只有操作实际处于需要优化的循环路径时,才会标记“修正❗️”。

    数据字典

    plugin_cf_r2_files

    字段类型可空默认值约束
    idid否-主键、自增
    user_iduint否--
    file_namestring否--
    object_keystring否--
    file_hashkey否''-
    urltext否--
    extstring否--
    mimestring否--
    sizeuint否--
    created_atuint否--

    plugin_cf_r2_local_files

    字段类型可空默认值约束
    idid否-主键、自增
    file_hashkey否-唯一
    file_namekey否-唯一
    remote_urlstring否''-
    original_namestring否''-
    extstring否''-
    sizeuint否0-
    is_imageINTEGER否0-
    first_seen_atuint否--
    checked_atuint否0-
    verified_atuint否0-
    verified_methodstring否''-
    local_deleted_atuint否0-
    fail_countuint否0-
    last_errorstring否''-
    #2
  • 583455189

    要钱

    #3
  • 9

    支持

    #4
  • george

    这个好 牛逼👏

    #5
  • code

    应该修正一下,如果上传成功到R2,自动删除本地服务器的图片,附件,或者插件可以搞个功能手动一键删除本地图片,附件。

    #6
  • bbs1org

    我看看

    #7
  • code

    我已经在二开了。

    #8
  • code

    一、R2 本地文件自动清理(新增功能)
    工作流程(user_files_remote_cleanup_cron,每 5 分钟一次的计划任务):

    发现:扫描本地仍存在物理文件的附件(app/upload/xx/hash.ext),登记到新表 plugin_user_files_remote_sync,以附件上传时间为起点计时
    延迟:只有超过你配置的延迟时间(分钟)才进入验证
    验证远端确实上传成功(删除前的强制确认,对文件/图片/附件统一处理),三级对比:
    HEAD 请求:远端 ETag 是 MD5 → 与本地 md5_file 比对;否则比对 Content-Length 与本地大小
    Range 探测:通过 Content-Range 总大小比对(应对分块传输的远端)
    全量下载:流式 MD5 比对(上限 256MB),确认内容完全一致
    删除:验证通过才 unlink 本地物理文件;只删文件,保留数据库记录;相同 hash+file_name 的多个附件记录(同内容多用户)统一处理
    验证失败会记录原因并重试,最多 10 次后放弃,不会误删
    后台设置(后台 → user_files → 概览页新增“远程存储本地清理”面板):

    远程存储公开地址(如 https://r2.bbs.tg,按 地址/存储文件名 拼接)
    上传后延迟删除分钟数(默认 60)
    开关 + “仅处理图片”选项
    实时统计:待处理 / 已验证 / 已删除本地 / 验证失败
    安全校验:拒绝凭据 URL 和内网地址
    二、编辑器重复链接问题(截图中的两个链接)
    原因是 attachment_upload 先插入本地 /app/upload/ 链接,R2 同步成功后又插入远端直链。做了两层修复:

    前端实时去重(编辑器内即时生效):JS 监听编辑器输入(含 2 秒轮询兜底),当同一文件名同时存在本地链接和远端直链时,自动移除本地链接——发布前编辑器里就只剩远端链接
    服务端兜底(topic.before_save / reply.before_save 钩子):保存主题/回复时再过滤一次,防止漏网
    去重仅在后台启用远程清理且地址有效时生效,且只匹配 64位hash.ext 格式的附件名,不会误伤普通文本。

    两点提醒:

    本地文件删除后,旧帖里的 /app/upload/ 本地链接和 a=attachment 下载会失效(内容在 R2 上仍有,但核心路由不会自动跳转);帖子应使用 R2 直链——去重逻辑正好保证新帖都走直链
    编辑器里插入本地链接的行为来自 attachment_upload 插件(不在本工作区),如果要根治“先插本地再插远端”的根源,最好也改那个插件的 JS;当前方案是在 user_files 层面做的完整兜底

    #9
  • code

    删除本地之前会对比一下是否CF储存里面有存在附件,图片。以免误删。

    #10
  • bbs1org

    那你直接提交改进版

    #11
  • code

    好的 图片描述

    #12
  • code

    版本 1.4.0 更新:
    更新支持删除本地图片,只保留R2的图片。

    #13
  • code

    paste-20260916-232416.png
    paste-20260916-232428.png
    paste-20260916-232439.png
    paste-20260916-232449.png
    paste-20260916-232458.png

    #14

发表回复

登录后回复