边缘安全加速平台 EO Blob

EdgeOne Makers Blob 是面向 Makers Functions 的分布式对象存储,适合存储图片、文档、用户上传文件等非结构化数据。默认提供最终一致的快速读取,写入后短暂时间内可读到最新值;如需立即读到最新值,可在单次读取时切换为强一致模式。

相关产品
边缘安全加速平台 EO 产品页,含版本规格、价格与购买入口。

三、数据访问

Blob 数据持久化在云端的对象存储中,并通过边缘节点加速读取。读取请求由离用户最近的边缘节点响应,毫秒级返回。

四、一致性模型

Blob 提供两种一致性模式,可按需选择:

模式 读取行为 适用场景
最终一致(默认) 走边缘缓存,速度最快;新写入的数据需要短暂时间(通常秒级)才能在所有节点上读到。 内容展示、缓存读取、容忍短暂不一致的业务。
强一致 跳过缓存直读主存储,保证读到最新值;读取耗时略高。 计数器、状态机、必须立即读到最新写入值的业务。

调用 store.get(key) 时默认使用最终一致;传入 { consistency: "strong" } 即切换到强一致。也可在 getStore 时统一指定整个 Store 的默认一致性。

注意:强一致性会增加读取耗时,仅在确有必要时使用。

六、用户文件上传

接收用户上传的头像、附件、图片等文件,存储到 Blob 中按用户或业务维度组织。

七、AI 生成内容

存储 AI 模型生成的图片、文档、报告,按批次或类型目录管理,方便检索和展示。

八、结构化数据集

将多个 JSON 文件按目录组织存放,通过 list 遍历处理整个数据集。

十、1. 安装 SDK

npm install @edgeone/pages-blob

十一、2. 在 Makers Functions 中使用

import { getStore } from "@edgeone/pages-blob";export async function onRequest({ request }) { const store = getStore("my-store"); // 写入 await store.set("hello.txt", "Hello, EdgeOne Makers!"); const content = await store.get("hello.txt"); return new Response(content);}

首次调用 getStore("my-store") 时,平台会自动为当前项目创建名为 my-store 的命名空间,后续调用直接使用已有的命名空间。

十二、3. 部署

部署 Makers 项目后,触发一次请求即可在控制台的 Blob 存储页面中看到已创建的命名空间和对象。

十三、控制台使用

Blob 在控制台中仅支持只读浏览(查看命名空间列表、浏览对象目录结构)。命名空间的创建和所有数据操作均通过 SDK 完成,详见下方 API 章节。

十四、API

import { getStore, listStores } from "@edgeone/pages-blob";

十五、getStore(name | options)

获取一个 Store 实例。getStore 接受两种入参:

·直接传入命名空间名称字符串,如 getStore("my-store")

·传入配置对象,如 getStore({ name, projectId, token, consistency })

在 Makers Functions 中

只需指定命名空间名称:

const store = getStore("my-store");// 也可使用对象形式,便于同时指定默认一致性const store = getStore({ name: "my-store", consistency: "strong" });

在 Makers Functions 之外访问(例如本地脚本、外部服务)

需要额外提供项目 ID 和 API Token:

const store = getStore({ name: "my-store", projectId: "pages-urtsvuwmfvli", token: "your-api-token",});

参数

参数 类型 必填 说明
name string 是 命名空间名称。
projectId string 在 Makers Functions 之外访问时必填 目标项目 ID。
token string 在 Makers Functions 之外访问时必填 API Token。
consistency "eventual" | "strong" 否 默认读取一致性,默认 "eventual"。

十六、store.set(key, value, options?)

写入一个对象。Key 已存在则覆盖。

await store.set("photos/cat.jpg", imageBuffer);await store.set("notes/todo.txt", "Buy milk");

参数

参数 类型 必填 说明
key string 是 对象的 Key。
value string | ArrayBuffer | Blob | ReadableStream 是 对象内容。

返回值

Promise<void>

十七、store.setJSON(key, value, options?)

写入 JSON 对象,自动序列化。接受与 store.set 相同的 options。

await store.setJSON("user/preferences", { theme: "dark", lang: "zh-CN" });

参数

参数 类型 必填 说明
key string 是 对象的 Key。
value any 是 可序列化为 JSON 的数据。

返回值

Promise<void>

十八、store.get(key, options?)

读取一个对象。Key 不存在时返回 null。

const text = await store.get("hello.txt");const json = await store.get("config.json", { type: "json" });const buffer = await store.get("image.png", { type: "arrayBuffer" });const blob = await store.get("video.mp4", { type: "blob" });const stream = await store.get("large-file.zip", { type: "stream" });// 强一致性读取const fresh = await store.get("counter", { consistency: "strong" });

参数

参数 类型 必填 说明
key string 是 对象的 Key。
options.type "text" | "json" | "arrayBuffer" | "blob" | "stream" 否 返回值类型,默认 "text"。
options.consistency "eventual" | "strong" 否 本次读取的一致性级别。

返回值

Promise<string | object | ArrayBuffer | Blob | ReadableStream | null>

十九、store.getWithHeaders(key, options?)

读取对象内容及其完整响应头。Key 不存在时返回 null。

const result = await store.getWithHeaders("document.pdf");// result.body — 对象内容// result.headers — 完整响应头(content-type, etag, cache-control 等)

参数

参数 类型 必填 说明
key string 是 对象的 Key。
options.consistency "eventual" | "strong" 否 本次读取的一致性级别。

返回值

Promise<{ body: string; headers: Record<string, string>;} | null>

20、store.delete(key)

删除一个对象。Key 不存在时不报错。

await store.delete("photos/cat.jpg");

参数

参数 类型 必填 说明
key string 是 需要删除的 Key。

返回值

Promise<void>

21、store.list(options?)

列举命名空间中的对象。默认自动聚合所有分页。

// 列出所有对象const { blobs } = await store.list();// 按前缀过滤const { blobs } = await store.list({ prefix: "photos/" });// 按目录分组(只返回当前层级的文件和子目录)const { blobs, directories } = await store.list({ prefix: "photos/", directories: true,});// 强一致性const { blobs } = await store.list({ consistency: "strong" });// 手动分页const page1 = await store.list({ paginate: false });const page2 = await store.list({ paginate: false, cursor: page1.cursor });

参数

参数 类型 必填 说明
options.prefix string 否 按 Key 前缀过滤。
options.directories boolean 否 设为 true 时按 / 分组,返回 directories 字段。
options.paginate boolean 否 设为 false 时返回单页结果(含 cursor)。
options.cursor string 否 从上一次分页的 cursor 继续列举。
options.consistency "eventual" | "strong" 否 本次列举的一致性级别。

返回值

{ blobs: Array<{ key: string; etag: string }>; directories?: string[]; // 仅 directories: true 时返回 cursor?: string; // 仅 paginate: false 时返回}

22、store.createUploadUrl(key, options?)

生成一个预签名的 PUT URL,允许浏览器或客户端直接把文件上传到 Blob,文件数据无需经过 Makers Functions 中转。适合大文件上传或对函数耗时敏感的场景,函数只负责签发一个几十字节的 URL,文件字节流直接从客户端流向 Blob。

const store = getStore("user-uploads");const { url, key, expiresAt } = await store.createUploadUrl("files/photo.jpg");

完整的客户端直传流程见下方客户端直传上传文件示例。

参数

参数 类型 必填 说明
key string 是 上传后对象的 Key。
options.expireSeconds number 否 URL 有效期(秒),默认 3600。
options.contentType string 否 若提供,客户端 PUT 时必须携带相同的 Content-Type 头,否则 403。

返回值

{ url: string; // 预签名 URL key: string; // 对象 Key expiresAt: number; // 过期时间(Unix 时间戳,单位秒)}

注意:生成的 URL 绑定 PUT 方法、指定的 Key、有效期窗口,以及 Content-Type(若设置)。任何不匹配的请求(其他方法、其他 Key、超出有效期、Content-Type 不一致)均返回 403。

23、listStores(options?)

列举当前项目下的所有命名空间。

import { listStores } from "@edgeone/pages-blob";// 在 Makers Functions 中const { stores } = await listStores();// 外部访问const { stores } = await listStores({ projectId: "pages-urtsvuwmfvli", token: "your-api-token",});

参数

参数 类型 必填 说明
options.projectId string 外部访问时必填 目标项目 ID
options.token string 外部访问时必填 API Token
options.consistency "eventual" | "strong" 否 读取一致性级别

返回值

{ stores: Array<{ name: string }>;}

25、客户端直传上传文件

通过预签名 URL 让浏览器直接把文件 PUT 到 Blob,函数只负责签发 URL,文件字节流不经过函数。适合大文件、批量上传等场景。

// 函数端:签发一次性上传 URLimport { getStore } from "@edgeone/pages-blob";export async function onRequest({ request }) { if (request.method !== "POST") { return new Response("Method not allowed", { status: 405 }); } const { name, contentType } = await request.json(); const store = getStore("user-uploads"); const { url, key, expiresAt } = await store.createUploadUrl( `uploads/${Date.now()}-${name}`, { expireSeconds: 3600, contentType: contentType || "application/octet-stream", } ); return new Response(JSON.stringify({ url, key, expiresAt }), { headers: { "Content-Type": "application/json" }, });}

// 浏览器端:取到 URL 后直接 PUT,无需 SDKasync function uploadFile(file) { // 1. 向函数申请上传 URL const { url, key } = await fetch("/api/get-upload-url", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: file.name, contentType: file.type }), }).then((r) => r.json()); // 2. 直接上传到 Blob await fetch(url, { method: "PUT", body: file, headers: { "Content-Type": file.type }, }); return key;}

26、按目录列出文件

import { getStore } from "@edgeone/pages-blob";export async function onRequest({ request }) { const store = getStore("user-uploads"); const url = new URL(request.url); const prefix = url.searchParams.get("path") || ""; const { blobs, directories } = await store.list({ prefix, directories: true, }); return new Response( JSON.stringify({ files: blobs, folders: directories }), { headers: { "Content-Type": "application/json" } } );}

27、示例模板

Blob SDK 用法示例:

预览地址

源码地址

赞 (0)
上一篇 4天前
下一篇 4天前