Skip to main content
生产环境服务器通常将文件读取、上传和写入到兼容 S3 的对象存储服务,而不是本地文件系统。传统上,这意味着你在开发环境中使用的本地文件系统 API 无法在生产环境中使用。当使用 Bun 时,情况就不同了。

Bun 的 S3 API 速度很快

Bun 的 S3 API 速度很快

左:Bun v1.1.44。右:Node.js v23.6.0

Bun 提供了快速、原生的绑定,用于与兼容 S3 的对象存储服务交互。其 S3 API 类似于 fetch 的 ResponseBlob API(就像 Bun 的本地文件系统 API 一样)。
s3.ts
S3 是事实上的标准互联网文件系统。Bun 的 S3 API 与兼容 S3 的存储服务一起使用,例如:
  • AWS S3
  • Cloudflare R2
  • DigitalOcean Spaces
  • MinIO
  • Backblaze B2
  • ……以及任何其他兼容 S3 的存储服务

基本用法

Bun.S3ClientBun.s3

Bun.s3 等同于 new Bun.S3Client(),依赖环境变量获取凭据。 要显式设置凭据,将其传递给 Bun.S3Client 构造函数。
s3.ts

操作 S3 文件

S3Clientfile 方法返回一个 对 S3 上文件的惰性引用
s3.ts
Bun.file(path) 一样,S3Clientfile 方法是同步的。在调用需要网络请求的方法之前,它不会发起任何网络请求。

从 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
你可以传递以下任意 ACL:

设置过期时间

要为预签名 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
在内部,Bun 使用 HTTP Range 头来仅请求你需要的字节。这个 slice 方法与 Blob.prototype.slice 相同。

从 S3 删除文件

要从 S3 删除文件,使用 delete 方法。
s3.ts
deleteunlink 相同。

错误码

当 Bun 的 S3 API 抛出错误时,该错误具有 code 属性,其值可能为:
  • ERR_S3_MISSING_CREDENTIALS
  • ERR_S3_INVALID_METHOD
  • ERR_S3_INVALID_PATH
  • ERR_S3_INVALID_ENDPOINT
  • ERR_S3_INVALID_SIGNATURE
  • ERR_S3_INVALID_SESSION_TOKEN
当 S3 服务本身返回错误时(即不是 Bun 的错误),它是一个 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:// 协议

fetchBun.file() 支持 s3:// 协议,因此同一套代码既适用于本地文件也适用于 S3 文件。
s3.ts
你也可以向 fetchBun.file 传递 s3 选项。
s3.ts

UTF-8、UTF-16 和 BOM(字节顺序标记)

ResponseBlob 一样,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。