大模型应用
在 Caffeine AI…
当需要为 Caffeine AI 应用添加文件上传、存储与展示(如图库、视频库、文档管理)时,用链下对象存储加链上引用,支持超出 IC 限制的大文件并通过浏览器缓存的 HTTP URL 访问。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
在 Caffeine AI 应用中实现链特定
解决思路
- 在 mops.toml 的 [dependencies] 中添加 caffeineai-object-storage 依赖。
- 在 main.mo 中通过 include MixinObjectStorage() 引入混入,导入路径必须是 "mo:caffeineai-object-storage/Mixin",不能使用相对路径。
- 所有表示文件、图片、照片、文档或媒体的数据字段必须使用 Storage.ExternalBlob 类型,绝不能使用 Text;接受文件上传的方法参数也必须用 Storage.ExternalBlob。
- 在前端安装 @caffeineai/object-storage npm 包,并在调用处使用 ExternalBlob.fromBytes(bytes, file.type, file.name)。
- 后端 mops 包与前端 npm 包必须同时安装;只装 npm 包会导致上传静默失败(存储网关返回 403)。
- 不要自己实现 _immutableObjectStorageCreateCertificate 或任何 _immutableObjectStorage* 方法,这些是平台保留方法,只能由 MixinObjectStorage 混入提供;手写实现会返回错误类型并导致 403 Forbidden: Invalid payload。
- 平台混入产生的正确签名是 _immutableObjectStorageCreateCertificate : (blobHash : Text) -> async record { method : Text; blob_hash : Text },任何其他返回类型(Blob、()、Text 等)都会导致网关校验失败。
- 将 include MixinObjectStorage() 放在 main.mo 中,而不是自定义 mixin 文件里;自己的文件跟踪逻辑放在单独的 mixin 中。
- 后端只存储引用,文件内容存于链下;前端负责实际的上传与下载。
- 上传时把浏览器 File 的 type 和 name 传入 fromBytes,以便网关 blob 树存储 Content-Type 和 Content-Disposition(原始文件名);同时把 file.name 传给后端以便应用记录保留文件名用于列表和 UI。
- 可用 withUploadProgress(onProgress) 获取上传进度百分比。
- 展示图片/视频时使用 blob.getDirectURL() 进行内联显示,它返回不透明的代理 URL,带浏览器缓存和流式传输。
- 绝不要通过检查 getDirectURL() 返回的 URL 来判断文件类型,因为它是没有扩展名的不透明代理 URL;应使用后端记录中的 filename 字段或 mimeType 字段判断。
- 下载并保留原始文件名时,使用 getBytes() 获取字节,包装成 Blob,创建 object URL,用带 download 属性的 anchor 触发下载,最后 revokeObjectURL。
- 验证后端 src/backend/mops.toml 的 [dependencies] 中已包含 caffeineai-object-storage(如 0.1.2),若缺失则运行 mops install 并重新构建。
- 遇到 403 Forbidden: Invalid payload 时,检查后端是否缺少 _immutableObjectStorageCreateCertificate 或返回类型错误,安装 mops 依赖、在 main.mo 添加 include MixinObjectStorage() 并重新部署。
- 遇到 Forbidden: Owner does not have an account with the cashier 时,重新部署后端 canister 以触发自愈注册。
适用边界 · 注意事项
- 不使用 Caffeine AI 平台或无法使用其 mops/npm 包的项目不适用。
- 需要纯链上存储、不依赖链下网关的场景不适用。