Bun 的 S3 API 速度很快

左:Bun v1.1.44。右:Node.js v23.6.0
Response 和 Blob API(就像 Bun 的本地文件系统 API 一样)。
s3.ts
- AWS S3
- Cloudflare R2
- DigitalOcean Spaces
- MinIO
- Backblaze B2
- ……以及任何其他兼容 S3 的存储服务
基本用法
Bun.S3Client 和 Bun.s3
Bun.s3 等同于 new Bun.S3Client(),依赖环境变量获取凭据。
要显式设置凭据,将其传递给 Bun.S3Client 构造函数。
s3.ts
操作 S3 文件
S3Client 的 file 方法返回一个 对 S3 上文件的惰性引用。
s3.ts
Bun.file(path) 一样,S3Client 的 file 方法是同步的。在调用需要网络请求的方法之前,它不会发起任何网络请求。
从 S3 读取文件
S3File 继承自 Blob,因此适用于 Blob 的方法同样适用于 S3File。
s3.ts
内存优化
像text()、json()、bytes() 或 arrayBuffer() 等方法在可能的情况下会避免在内存中重复复制字符串或字节。
如果文本恰好是 ASCII 编码,Bun 会将字符串直接传递给 JavaScriptCore(引擎),无需转码,也无需在内存中复制。.bytes() 和 .arrayBuffer() 也同样避免在内存中复制字节。
写入和上传文件到 S3
写入 S3 的方式相同。s3.ts
处理大文件(流)
Bun 自动处理大文件的分片上传,并支持流式传输。适用于本地文件的同一 API 也适用于 S3 文件。s3.ts
预签名 URL
当你的生产服务需要允许用户上传文件到服务器时,让用户直接上传到 S3 通常比通过你的服务器中转更可靠。 为此,可以对 S3 文件使用预签名 URL。预签名会生成一个带签名的 URL,允许用户将特定文件上传到 S3,而无需暴露你的凭据或授予他们对存储桶的不必要访问权限。 默认情况下,Bun 生成一个 24 小时后过期的GET URL。
s3.ts
设置 ACL
要在预签名 URL 上设置 ACL(访问控制列表),传递acl 选项:
s3.ts
设置过期时间
要为预签名 URL 设置过期时间,传递expiresIn 选项。
s3.ts
method
要为预签名 URL 设置 HTTP 方法,传递 method 选项。
s3.ts
new Response(S3File)
要将用户重定向到 S3 文件的预签名 URL,将 S3File 实例作为 body 传递给 Response 对象。
该响应会将用户重定向到 S3 文件的预签名 URL,从而节省将文件下载到服务器再发送给用户的内存、时间和带宽成本。
s3.ts
对兼容 S3 服务的支持
Bun 的 S3 实现适用于任何兼容 S3 的存储服务。指定相应的 endpoint:在 AWS S3 上使用 Bun 的 S3Client
AWS S3 是默认值。使用 AWS S3 时,可以传递region 选项而不是 endpoint 选项。
s3.ts
在 Google Cloud Storage 上使用 Bun 的 S3Client
要在 Google Cloud Storage 上使用 Bun 的 S3 客户端,在S3Client 构造函数中将 endpoint 设置为 "https://storage.googleapis.com"。
s3.ts
在 Cloudflare R2 上使用 Bun 的 S3Client
要在 Cloudflare R2 上使用 Bun 的 S3 客户端,在S3Client 构造函数中将 endpoint 设置为 R2 endpoint。R2 endpoint 包含你的账户 ID。
s3.ts
在 DigitalOcean Spaces 上使用 Bun 的 S3Client
要在 DigitalOcean Spaces 上使用 Bun 的 S3 客户端,在S3Client 构造函数中将 endpoint 设置为 DigitalOcean Spaces endpoint。
s3.ts
在 MinIO 上使用 Bun 的 S3Client
要在 MinIO 上使用 Bun 的 S3 客户端,在S3Client 构造函数中将 endpoint 设置为 MinIO 运行的 URL。
s3.ts
在 Supabase 上使用 Bun 的 S3Client
要在 Supabase 上使用 Bun 的 S3 客户端,在S3Client 构造函数中将 endpoint 设置为 Supabase endpoint。Supabase endpoint 包含你的账户 ID 和 /storage/v1/s3 路径。在 Supabase 控制台的 https://supabase.com/dashboard/project/<account-id>/settings/storage 中,打开 Enable connection via S3 protocol 并使用该部分显示的 region。
s3.ts
使用 Bun 的 S3Client 与 S3 虚拟主机样式 endpoint
使用虚拟主机样式 endpoint 时,将virtualHostedStyle 选项设置为 true。
- 如果不指定 endpoint,Bun 会根据提供的 region 和 bucket 确定 AWS S3 endpoint。 - 如果未指定 region,Bun 默认使用
us-east-1。 - 如果显式提供了 endpoint,则无需指定 bucket 名称。
s3.ts
凭据
默认情况下,Bun 从以下环境变量读取凭据。
对于每个选项,如果未设置
S3_* 环境变量,Bun 会回退到对应的 AWS_* 环境变量。
Bun 在初始化时从
.env 文件或进程环境中读取这些环境变量(不通过 process.env 读取)。
传递给你调用 s3.file(credentials)、new Bun.S3Client(credentials) 或任何接受凭据的方法的选项会覆盖这些默认值。因此,如果你对不同的 bucket 使用相同的凭据,可以在 .env 文件中设置一次凭据,然后只向 s3.file() 传递 bucket: "my-bucket"。
S3Client 对象
当你不使用环境变量,或使用多个 bucket 时,创建一个 S3Client 对象来显式设置凭据。
s3.ts
S3Client.prototype.write
要上传或写入文件到 S3,在 S3Client 实例上调用 write 方法。
s3.ts
S3Client.prototype.delete
要从 S3 删除文件,在 S3Client 实例上调用 delete 方法。
s3.ts
S3Client.prototype.exists
要检查 S3 中文件是否存在,在 S3Client 实例上调用 exists 方法。
s3.ts
S3File
在 S3Client 实例上调用 file(),或调用 s3.file(),会返回一个 S3File。与 Bun.file() 一样,S3File 实例是惰性的:它们并不指向创建时必然存在的对象。这就是为什么所有不涉及网络请求的方法都是完全同步的。
Type Reference
Bun.file() 一样,S3File 继承自 Blob,因此 Blob 上的所有方法也可用于 S3File。从本地文件读取数据的同一 API 也可以从 S3 读取数据。
这意味着
S3File 实例可以与 fetch()、Response 以及其他接受 Blob 实例的 Web API 一起使用。
使用 slice 进行部分读取
要读取文件的部分范围,使用 slice 方法。
s3.ts
Range 头来仅请求你需要的字节。这个 slice 方法与 Blob.prototype.slice 相同。
从 S3 删除文件
要从 S3 删除文件,使用delete 方法。
s3.ts
delete 与 unlink 相同。
错误码
当 Bun 的 S3 API 抛出错误时,该错误具有code 属性,其值可能为:
ERR_S3_MISSING_CREDENTIALSERR_S3_INVALID_METHODERR_S3_INVALID_PATHERR_S3_INVALID_ENDPOINTERR_S3_INVALID_SIGNATUREERR_S3_INVALID_SESSION_TOKEN
S3Error 实例(名称为 "S3Error" 的 Error 实例)。
S3Client 静态方法
S3Client 类提供了几个用于与 S3 交互的静态方法。
S3Client.write(静态)
要将数据直接写入 bucket 中的路径,使用 S3Client.write 静态方法。
s3.ts
new S3Client(credentials).write("my-file.txt", "Hello World")。
S3Client.presign(静态)
要为 S3 文件生成预签名 URL,使用 S3Client.presign 静态方法。
s3.ts
new S3Client(credentials).presign("my-file.txt", { expiresIn: 3600 })。
S3Client.list(静态)
要列出 bucket 中的部分或全部对象(最多 1000 个),使用 S3Client.list 静态方法。
s3.ts
new S3Client(credentials).list()。
S3Client.exists(静态)
要检查 S3 文件是否存在,使用 S3Client.exists 静态方法。
s3.ts
S3File 实例。
s3.ts
S3Client.size(静态)
要检查 S3 文件的大小而不下载它,使用 S3Client.size 静态方法。
s3.ts
new S3Client(credentials).size("my-file.txt")。
S3Client.stat(静态)
要获取 S3 文件的大小、etag 和其他元数据,使用 S3Client.stat 静态方法。
s3.ts
S3Client.delete(静态)
要删除 S3 文件,使用 S3Client.delete 静态方法。
s3.ts
s3:// 协议
fetch 和 Bun.file() 支持 s3:// 协议,因此同一套代码既适用于本地文件也适用于 S3 文件。
s3.ts
fetch 和 Bun.file 传递 s3 选项。
s3.ts
UTF-8、UTF-16 和 BOM(字节顺序标记)
与Response 和 Blob 一样,S3File 默认假定为 UTF-8 编码。
在 S3File 上调用 text() 或 json() 时:
- 当 Bun 检测到 UTF-16 字节顺序标记(BOM)时,它会将数据视为 UTF-16 编码。JavaScriptCore 原生支持 UTF-16,因此 Bun 跳过 UTF-8 转码步骤(并去除 BOM)。一个后果:UTF-16 字符串中的无效代理对会原样传递到 JavaScriptCore(与源代码相同)。
- 当 Bun 检测到 UTF-8 BOM 时,它会去除 BOM,并用 Unicode 替换字符(
\uFFFD)替换无效的 UTF-8 码点,然后将字符串传递给 JavaScriptCore。 - 不支持 UTF-32。