如何在删除数据的同时清理 OSS 中的图片?
项目访问链接
https://zion.functorz.com/tool/mwLZrNjrvKn/WEB?code=gLxDKo1F20M97&ref=4857164
简介
- 目标:实现数据库记录删除时,自动检测并删除 OSS(对象存储)中对应的物理图片文件。
- 适用场景:图片管理类应用、电商产品图管理、用户头像清理等需要优化存储成本的场景。
- 核心逻辑:配置“数据库内容变化”触发器 -> 触发后端行为流 -> 运行代码节点判断引用关系 -> 执行 OSS 文件删除。
默认情况下,Zion 删除数据库中的图片字段记录仅会删除该条“引用记录”,而不会删除 OSS 中实际存储的文件。这是为了防止该图片被其他地方引用时出现死链。
实现步骤
数据存储
数据模型
为了演示该功能,我们需要创建一个包含图片字段的简单数据表。
表:image
用于模拟存储图片数据的业务表。
| 字段名称 | 类型 | 说明 |
|---|---|---|
| image | 图片 | 存储上传到 OSS 的图片文件 |
逻辑与状态配置
我们需要构建一个后端行为流来处理删除逻辑,并将其与数据库触发器绑定。
行为流构造:删除oss中的图片
-
新建行为流:在顶部导航栏进入“行为流”模式,新建一个行为流,命名为
删除oss中的图片。 -
定义输入参数:
- 点击“输入”节点,新增参数
imageId;类型设置为 长整数 (BIGINT),用于接收需要清理的图片 ID。
- 点击“输入”节点,新增参数
-
运行代码 (Run Code):添加一个“运行代码”节点。
- 输入映射:将行为流输入的
imageId绑定到代码节点的输入参数上。 - 代码逻辑:在代码编辑器中编写逻辑。核心逻辑是拿到
imageId后,调用删除接口,如果这个图片在其他地方被引用,则删除失败,防止出现死链。
//未登录不允许调用这个gql const imageId = context.getArg('imageId'); const gql = `mutation deleteImageByIdIfExists($imageId:bigint!){ deleteImageByIdIfExists(imageId:$imageId) }`; const isSuccess = context.runGql('deleteImageByIdIfExists',gql, { imageId },{ role: 'admin' }).deleteImageByIdIfExists; context.setReturn('isSuccess',isSuccess); - 输入映射:将行为流输入的
在富文本中的图片链接无法被识别,存在死链的风险。
- 定义输出参数:
- 点击“输出”节点,新增参数
isSuccess;类型设置为 布尔值 (Boolean),绑定代码节点的执行结果。
- 点击“输出”节点,新增参数
触发器配置
为了实现自动化,我们需要在数据库发生删除动作时自动执行上述行为流。
- 添加触发器:在行为流页面的右侧面板,点击“触发器”选项卡,选择 数据库内容变化。
- 配置触发条件:
- 数据表:选择
image表。 - 触发时机:选择 数据删除时。
- 数据表:选择
- 绑定行为流:
- 在“行为流输入”部分,将参数
imageId赋值为当前删除项的 image.id(即被删除图片的 ID)。
- 在“行为流输入”部分,将参数
⚠️
注意:OSS 存储容量的更新可能存在延迟,删除操作完成后,控制台的存储占用数据可能不会实时刷新。
UI 搭建与交互
- 列表展示:在页面中添加一个 列表 (List) 组件,绑定
image数据表。
- 删除按钮:在列表项中添加一个按钮(如“删除”图标)。
- 行为配置:点击时 -> 删除数据:选择删除当前行记录。
- 删除数据成功时 -> 刷新:选择
列表。
- 图片展示:在列表项中添加一个图片组件,绑定
image数据表的image字段。
4. 验证
步骤 1:上传与删除测试
在预览模式下,向 image 表上传几张图片,然后点击 UI 上的删除按钮。
预期结果:数据库中的记录立即消失。
步骤 2:OSS 后台校验
登录 Zion 管理后台或查看对象存储监控。
预期结果:对应的图片文件已从 OSS 存储中移除,存储空间占用在延迟刷新后有所下降。
步骤 3:引用保护测试(进阶)
如果同一张图片被两个不同的记录引用,尝试删除其中一个记录。
预期结果:由于代码节点中包含 deleteImageByIdIfExist 的逻辑判断,OSS 中的物理文件应继续保留,直到最后一个引用被删除。
Last updated on