其他
在 Netlify 项目中存取文件、JSON…
适用于 Netlify Functions/Edge Functions/Build Plugins 中处理非结构化对象、文件上传、JSON、部署内资产或类缓存状态;不适用于按用户、事务或关系型数据。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 35/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 39/100 ×0.15
适用场景
在 Netlify 项目中存取文件、JS特定
解决思路
- 从 `@netlify/blobs` 导入 `getStore`,调用 `getStore('store-name')` 打开站点级 store,然后用 `set`、`get` 等操作;运行时需要 Fetch API(Node.js 18+)。
- 需要按部署隔离时,从 `@netlify/blobs` 导入 `getDeployStore`,调用 `getDeployStore('store-name')` 打开部署级 store。
- Build Plugin 中:读取任意站点 store 可用 `getStore`,但写入只能用部署专用 store(`getDeployStore`);同时说明这两半。
- 选择 store:`getStore(name)` 是站点级,跨部署持久,所有上下文可读;`getDeployStore(name)` 限定单次部署,用于隔离以及 Build Plugin 或基于文件上传的写入。
- 打开 store 支持位置参数形式 `getStore(name, { region, siteID, token })` / `getDeployStore(name, { deployID, region, siteID, token })`,也支持对象形式 `getStore({ name, consistency, region, siteID, token, fetch })`。
- 在 Functions/Edge Functions/Build Plugins 内,`siteID`、`deployID`、`token` 会自动设置;只在需要覆盖时显式传入(例如另一个你拥有的 site 的 `siteID`)。
- `region` 仅对 `getDeployStore` 自动设置(默认函数区域);对 `getStore` 不自动设置,默认 `us-east-2`。Site ID 等于 API `site_id`、`NETLIFY_SITE_ID`、UI 的 Project ID。
- 持久化上传:在 Function 中用 `req.formData()` 取 `File`,用 `uuid()` 生成 key,调用 `uploads.set(uuid(), file, { metadata: { country: context.geo.country.name } })`,返回 `Response`。
- 持久化 JSON:用 `setJSON(key, data, { metadata: { ... } })`。
- 读取 blob:用 `get(key)`;返回 `null` 表示不存在,可据此返回 404。
- 读取并带 metadata:用 `getWithMetadata(key)`,解构 `{ data, metadata }`。
- 删除单个 key:用 `delete(key)`;删除整个 store:用 `deleteAll()`,返回 `{ deletedBlobs }`,store 不存在时为 0。
- Store-opening API:`getStore`、`getDeployStore`、`listStores` 从 `@netlify/blobs` 导入。
- Store 实例方法包括:`get`、`getWithMetadata`、`getMetadata`、`set`、`setJSON`、`list`、`delete`、`deleteAll`。
- `set(key, value, { metadata, onlyIfMatch, onlyIfNew })`:`value` 为 `ArrayBuffer | Blob | string`;默认覆盖;返回 `{ modified, etag }`。
- `setJSON(key, value, { metadata, onlyIfMatch, onlyIfNew })`:同上,`value` 为任意可 JSON 序列化值。
- `get(key, { consistency, type })`:`type` 为 `text`(默认)/ `json` / `arrayBuffer` / `blob` / `stream`;返回 value 或 `null`。
- `getWithMetadata(key, { consistency, etag, type })`:返回 `{ data, etag, metadata }` 或 `null`;若传入的 `etag` 匹配,则 `data` 为 `null`,表示缓存仍新鲜。
- `getMetadata(key, { consistency, etag, type })`:返回 `{ metadata, etag }` 或 `null`;可在不下载 blob 的情况下检查存在性。
- `list({ directories, paginate, prefix })`:返回 `{ blobs: [{ etag, key }], directories: string[] }`。
- `listStores({ paginate })`:返回 `{ stores: string[] }`;不包含部署专用 store。
- `delete(key)`:返回 `undefined`。
- `deleteAll()`:返回 `{ deletedBlobs }`;删除 store 等同于删除其所有 blobs。
- 原子条件写入:`onlyIfNew: true` 仅当 key 不存在时写入;`onlyIfMatch: etag` 仅当当前 ETag 匹配时写入(乐观并发);检查返回的 `modified` 判断成功或失败。
- 条件写入示例:`const { modified } = await emails.set('jane@netlify.com', 'Jane Doe', { onlyIfNew: true }); if (!modified) return new Response('Email already exists', { status: 400 });` 但仅用于单 key 的 create-if-absent / compare-and-set,不要用于构建事务计数器。
- 用 `/` 分组 key 实现层级:`list({ directories: true })` 返回顶层 `directories` 及根 blobs;用 `prefix` 下钻,prefix 必须包含尾部斜杠(如 `cats/`),否则 `catsuit` 也会匹配。
- 分页:服务端每页最多 1000 条(`list`)/ 1000 个 store(`listStores`);默认自动处理;传 `paginate: true` 得到 `AsyncIterator`,可用 `for await (const entry of store.list({ paginate: true }))`。
- 条件请求或本地缓存:给 `getWithMetadata` / `getMetadata` 传缓存的 `etag`;匹配则 `data` 为 `null`。比较时包含外围引号和 weakness 前缀。
- 一致性配置:默认 eventual(单区域、边缘缓存,60s 内传播);可 per store 或 per read 选择 strong:`getStore({ name: 'animals', consistency: 'strong' })` 或 `store.get('dog', { consistency: 'strong' })`。Netlify CLI 总是使用 strong consistency。
- 有效区域比 function regions 少:`us-east-1`、`us-east-2`、`eu-central-1`、`ap-southeast-1`、`ap-southeast-2`。
- 部署专用 store(`getDeployStore`)默认跟随函数区域;在 Functions/Edge Functions/Build Plugins 中 `region` 自动设置。覆盖示例:`getDeployStore({ name: 'file-uploads', region: 'ap-southeast-2' })`。
- 站点级 store(`getStore`)默认 `us-east-2`,不跟随函数区域;这里 `region` 从不自动设置。覆盖示例:`getStore({ name: 'user-profiles', region: 'eu-central-1' })`。
- 区域坑:站点级 store 要访问非默认区域数据,必须让每一个 `getStore` 调用(读、写、删)都传相同 `region`;省略会静默使用 `us-east-2`,且不报错。改 store 区域不会迁移数据:新区域看似为空,旧数据留在旧区域。迁移需逐条复制到新区域打开的 store,再从旧 store 删除。
- 自定义 fetch:若不能用 Node.js 18,传入自己的 `fetch`:`getStore({ fetch, name: 'file-uploads' })`。
- 基于文件上传(部署专用 store):面向框架或工具作者、无 build plugin 集成时,把 blob 文件放在站点 base 目录下的 `.netlify/blobs/deploy`;Netlify 在构建后、部署前上传它们并保留目录结构。
- 文件上传注意:Netlify 每次构建前删除 `.netlify/blobs/deploy`;提交到仓库的文件不会被上传。必须在构建期间(构建命令或插件)创建 blob 文件。
- 文件上传 metadata:用同级 JSON 文件,文件名前缀 `$` 且以 `.json` 结尾,对应 blob 文件名;例如 `dogs/good-boy.jpg` 配 `dogs/$good-boy.jpg.json`;没有 metadata 的文件如 `mouse.jpg`。metadata 文件必须是合法 JSON,否则部署失败。需要 continuous deployment 或 CLI deploys。
- 部署专用 store 生命周期:回滚时保持同步;随自动 deploy deletion 清理。下载 deploy 不会下载部署专用 blobs。锁定已发布 deploy 不会阻止写入其部署专用 stores。
- 过期(无内置 TTL):自己实现:`set` 时在 metadata 里放 timestamp;用 `getWithMetadata` 检查;过期则 `delete`。
- CLI:`netlify blobs:list/get/set/delete` 可用于检查;参考 CLI blobs 命令文档。CLI 总是使用 strong consistency,且需要站点级 store。
- 本地开发:Netlify Dev 使用沙箱本地 store;不支持 file-based uploads,且不能在本地读取生产数据。
- 约束:store 名称不能含 `/` 或 `:`,最大 64 bytes。
- 约束:key 非空,不能以 `/` 开头,任意 Unicode,最大 600 bytes。
- 约束:对象最大 5 GB;metadata 最大 2 KB。注意是字节限制,不是字符数;某些 UTF-8 字符是多字节。
- Blobs 静态加密(at rest 和 in transit);只能通过你自己的站点访问。
- 不属于 Netlify HIPAA-compliant hosting;如涉及 HIPAA 合规托管则不要用。使用第三方 build plugin 访问 blobs 前先审查其代码。
- 迁移 `@netlify/blobs` 6.5.0 → 7.0.0:v6.5.0 或更早写入的站点级 store 升级后不可访问(命名空间变更)。用最新 Netlify CLI 逐 store 迁移:`netlify recipes blobs-migrate YOUR_STORE_NAME`;迁移后 v7.0.0+ 可访问。
- 组织规则:Blobs 不是数据库;动态、按用户、事务数据用 Netlify DB;Blobs 用于对象、文件、类缓存状态。
- 失败时:暴露错误并读 function logs;不要发明 REST endpoint 或 side-channel API 来重试。
- CLI inspection 命令以 CLI 参考文档为准,链接而不是复述。
- 访问控制:无内置访问控制;服务函数就是门。默认私有:把读放在已认证 function 后面,不要公开暴露 blobs。把用户输入视为不安全;不要服务任意调用者提供的 key;用调用者无法篡改的东西限定 key。
- Site-scoped stores 跨所有 deploy context 共享:deploy preview 代码会读、覆盖、删除生产数据。不要从 preview 跑 destructive tests 或 seed throwaway data;用 `getDeployStore()` 或上下文特定 store 名称隔离。
- 不要基于 blob key 构建 counter、balance 或 read-modify-write 逻辑,即使有 `onlyIfMatch` 重试;那是事务数据,用 Netlify DB。
- Build plugins:同时说明两半:可读任何站点 store,但只能写 deploy-specific store(`getDeployStore`)。
适用边界 · 注意事项
- 不要把 Blobs 用于动态、按用户、事务或关系型数据;这类需求用 Netlify DB。
- Go 编写的 Functions 不能访问 Netlify Blobs。
- 需要 Netlify HIPAA 合规托管时不要使用 Blobs。