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.S3Client & Bun.s3

Bun.s3 等同于 new Bun.S3Client(),依赖环境变量中的凭据。 若需显式设置凭据,可通过构造函数传递给 Bun.S3Client
s3.ts

处理 S3 文件

S3Client 中的 file 方法返回对 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 过期时间

设置预签名 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 的存储服务。指定适当的端点:

使用 Bun 的 S3Client 连接 AWS S3

AWS S3 是默认选项。使用 AWS S3 时,可以传递 region 选项,而不是 endpoint 选项。
s3.ts

使用 Bun 的 S3Client 连接 Google Cloud Storage

使用 Bun 的 S3 客户端连接 Google Cloud Storage,在 S3Client 构造器中将 endpoint 设置为 "https://storage.googleapis.com"
s3.ts

使用 Bun 的 S3Client 连接 Cloudflare R2

使用 Bun 的 S3 客户端连接 Cloudflare R2,在 S3Client 构造器中将 endpoint 设置为包含你的账号 ID 的 R2 端点。
s3.ts

使用 Bun 的 S3Client 连接 DigitalOcean Spaces

使用 Bun 的 S3 客户端连接 DigitalOcean Spaces,在 S3Client 构造器中将 endpoint 设置为对应区域的 DigitalOcean Spaces 端点。
s3.ts

使用 Bun 的 S3Client 连接 MinIO

使用 Bun 的 S3 客户端连接 MinIO,在 S3Client 构造器中将 endpoint 设置为 MinIO 运行的 URL。
s3.ts

使用 Bun 的 S3Client 连接 supabase

使用 Bun 的 S3 客户端连接 Supabase,在 S3Client 构造器中将 endpoint 设置为 Supabase 端点。Supabase 端点包含你的账号 ID 和 /storage/v1/s3 路径。在 Supabase 控制台的 https://supabase.com/dashboard/project/<account-id>/settings/storage 中,开启 Enable connection via S3 protocol,并使用该部分显示的区域。
s3.ts

使用 Bun 的 S3Client 连接 S3 虚拟主机式端点

使用虚拟主机式端点时,将 virtualHostedStyle 选项设置为 true
  • 如果未指定端点,Bun 会根据提供的区域和存储桶确定 AWS S3 端点。- 如果未指定 区域,Bun 默认使用 us-east-1。- 如果显式提供端点,则无需指定 存储桶名称。
s3.ts

凭据

默认情况下,Bun 会读取以下环境变量作为凭据。 对于每个选项,如果未设置 S3_* 环境变量,Bun 会回退使用对应的 AWS_* 环境变量。 Bun 会在初始化时从 .env 文件 或进程环境中读取这些环境变量(不会使用 process.env)。 你传递给 s3.file(credentials)new Bun.S3Client(credentials) 或任何接受凭据的方法的选项会覆盖这些默认值。因此,如果你对不同的存储桶使用相同的凭据,可以在 .env 文件中设置一次凭据,然后只将 bucket: "my-bucket" 传递给 s3.file()

S3Client 对象

如果你不使用环境变量,或者正在使用多个存储桶,可以创建一个 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

要直接将数据写入存储桶中的某个路径,请使用 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

要列出存储桶中的部分或全部对象(最多 1,000 个),请使用 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 编码。 调用 S3Filetext()json() 时:
  • 当 Bun 检测到 UTF-16 字节顺序标记(BOM)时,会将数据视为 UTF-16。JavaScriptCore 原生支持 UTF-16,因此 Bun 会跳过 UTF-8 转码步骤(并移除 BOM)。由此产生的一个结果是,UTF-16 字符串中的无效代理项对会直接传递给 JavaScriptCore(与源代码相同)。
  • 当 Bun 检测到 UTF-8 BOM 时,会移除 BOM,并在将字符串传递给 JavaScriptCore 之前,将无效的 UTF-8 码点替换为 Unicode 替换字符(\uFFFD)。
  • 不支持 UTF-32。