Documentation Index
Fetch the complete documentation index at: https://bun.zhcndoc.com/llms.txt
Use this file to discover all available pages before exploring further.
生产服务器通常读取、上传和写入文件到兼容 S3 的对象存储服务,而不是本地文件系统。历史上这意味着开发时使用的本地文件系统 API 无法在生产环境中使用。但使用 Bun,情况则有所不同。
Bun 的 S3 API 很快
Bun 为与兼容 S3 的对象存储服务交互提供了快速的原生绑定。其 S3 API 设计得感觉类似于 fetch 的 Response 和 Blob API(就像 Bun 的本地文件系统 API 一样)。
s3.tsimport { s3, write, S3Client } from "bun";
// Bun.s3 会读取环境变量中的凭据
// file() 返回对 S3 上文件的惰性引用
const metadata = s3.file("123.json");
// 从 S3 下载 JSON
const data = await metadata.json();
// 上传到 S3
await write(metadata, JSON.stringify({ name: "John", age: 30 }));
// 预签名 URL(同步 - 无需网络请求)
const url = metadata.presign({
acl: "public-read",
expiresIn: 60 * 60 * 24, // 1 天
});
// 删除文件
await metadata.delete();
S3 是 事实上的标准互联网文件系统。Bun 的 S3 API 支持与以下兼容 S3 的存储服务协作:
- AWS S3
- Cloudflare R2
- DigitalOcean Spaces
- MinIO
- Backblaze B2
- …以及其他任何兼容 S3 的存储服务
基本用法
有多种方式可与 Bun 的 S3 API 进行交互。
Bun.S3Client & Bun.s3
Bun.s3 等同于 new Bun.S3Client(),依赖环境变量中的凭据。
若需显式设置凭据,可通过构造函数传递给 Bun.S3Client。
s3.tsimport { S3Client } from "bun";
const client = new S3Client({
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
bucket: "my-bucket",
// sessionToken: "..."
// acl: "public-read",
// endpoint: "https://s3.us-east-1.amazonaws.com",
// endpoint: "https://<account-id>.r2.cloudflarestorage.com", // Cloudflare R2
// endpoint: "https://<region>.digitaloceanspaces.com", // DigitalOcean Spaces
// endpoint: "http://localhost:9000", // MinIO
});
// Bun.s3 是一个全局单例,等同于 `new Bun.S3Client()`
处理 S3 文件
S3Client 中的 file 方法返回对 S3 上文件的 惰性引用。
s3.ts// 对 S3 上文件的惰性引用
const s3file: S3File = client.file("123.json");
类似于 Bun.file(path),S3Client 的 file 方法是同步的。直到调用依赖网络请求的方法前,它不会进行任何网络请求。
从 S3 读取文件
如果你用过 fetch API,就对 Response 和 Blob API 非常熟悉。S3File 继承自 Blob。所有适用于 Blob 的方法也适用于 S3File。
s3.ts// 将 S3File 作为文本读取
const text = await s3file.text();
// 将 S3File 作为 JSON 读取
const json = await s3file.json();
// 将 S3File 作为 ArrayBuffer 读取
const buffer = await s3file.arrayBuffer();
// 仅获取前 1024 字节
const partial = await s3file.slice(0, 1024).text();
// 流式读取文件
const stream = s3file.stream();
for await (const chunk of stream) {
console.log(chunk);
}
内存优化
像 text()、json()、bytes() 或 arrayBuffer() 这样的方法会尽量避免在内存中复制字符串或字节。
如果文本恰好是 ASCII,Bun 会直接将字符串传输给 JavaScriptCore(引擎),无需转码,也不会复制字符串副本。使用 .bytes() 或 .arrayBuffer() 时,也会避免复制字节。
这些辅助方法不仅让 API 更简洁,还提高了速度。
写入与上传文件至 S3
写入到 S3 的方式也一样。
s3.ts// 写入一个字符串(替换文件)
await s3file.write("Hello World!");
// 写入一个 Buffer(替换文件)
await s3file.write(Buffer.from("Hello World!"));
// 写入一个 Response(替换文件)
await s3file.write(new Response("Hello World!"));
// 带内容类型写入
await s3file.write(JSON.stringify({ name: "John", age: 30 }), {
type: "application/json",
});
// 使用内容编码写入(例如用于预压缩数据)
await s3file.write(compressedData, {
type: "application/json",
contentEncoding: "gzip",
});
// 使用内容处置写入
await s3file.write(pdfData, {
type: "application/pdf",
contentDisposition: 'attachment; filename="report.pdf"',
});
// 使用 writer(流式)
const writer = s3file.writer({ type: "application/json" });
writer.write("Hello");
writer.write(" World!");
await writer.end();
// 使用 Bun.write 写入
await Bun.write(s3file, "Hello World!");
处理大文件(流)
Bun 会自动处理大文件的分块上传,并支持流式写入。本地文件适用的 API 同样适用于 S3 文件。
s3.ts// 写入大文件
const bigFile = Buffer.alloc(10 * 1024 * 1024); // 10MB
const writer = s3file.writer({
// 遇到网络错误自动重试最多 3 次
retry: 3,
// 同时排队最多 10 个请求
queueSize: 10,
// 以 5MB 分块上传
partSize: 5 * 1024 * 1024,
});
for (let i = 0; i < 10; i++) {
writer.write(bigFile);
await writer.flush();
}
await writer.end();
预签名 URL
当你的生产服务需要允许用户上传文件时,通常让用户直接上传到 S3 比你的服务器作为中介更可靠。
为此,你可以为 S3 文件预签名 URL。此 URL 包含签名,允许用户安全地上传指定文件到 S3,而不会暴露你的凭据或授予他们对桶的额外访问权限。
默认情况下,预签名 URL 是一个 24 小时后过期的 GET 请求。Bun 会尝试根据文件扩展名推断内容类型。如果不能推断,默认使用 application/octet-stream。
s3.tsimport { s3 } from "bun";
// 生成一个 24 小时后过期的预签名 URL(默认)
const download = s3.presign("my-file.txt"); // GET,text/plain,24 小时后过期
const upload = s3.presign("my-file", {
expiresIn: 3600, // 1 小时
method: "PUT",
type: "application/json", // 设置预签名 URL 中的响应内容类型
});
// 使用内容处置进行预签名(例如强制使用特定文件名进行下载)
const downloadUrl = s3.presign("report.pdf", {
expiresIn: 3600,
contentDisposition: 'attachment; filename="quarterly-report.pdf"',
});
// 如果已有文件引用,也可以调用 .presign(),但应避免频繁这样做
// 以减少内存占用。
const myFile = s3.file("my-file.txt");
const presignedFile = myFile.presign({
expiresIn: 3600, // 1 小时
});
设置 ACL
要为预签名 URL 设置 ACL(访问控制列表),传入 acl 选项:
s3.tsconst url = s3file.presign({
acl: "public-read",
expiresIn: 3600,
});
你可以传入以下 ACL:
| ACL | 说明 |
|---|
"public-read" | 对象可被公开读取。 |
"private" | 对象仅桶所有者可读取。 |
"public-read-write" | 对象可被公开读取和写入。 |
"authenticated-read" | 桶所有者和已认证用户可读取。 |
"aws-exec-read" | 发送请求的 AWS 账户可读取对象。 |
"bucket-owner-read" | 桶所有者可读取对象。 |
"bucket-owner-full-control" | 桶所有者可读写对象。 |
"log-delivery-write" | AWS 用于日志传递的服务可以写入对象。 |
设置 URL 过期时间
设置预签名 URL 的过期时间,传入 expiresIn 选项。
s3.tsconst url = s3file.presign({
// 秒数
expiresIn: 3600, // 1 小时
// 访问控制列表
acl: "public-read",
// HTTP 方法
method: "PUT",
});
method
设置预签名 URL 的 HTTP 方法,传入 method 选项。
s3.tsconst url = s3file.presign({
method: "PUT",
// method: "DELETE",
// method: "GET",
// method: "HEAD",
// method: "POST",
// method: "PUT",
});
new Response(S3File)
要将用户重定向到 S3 文件的预签名 URL,请将一个 S3File 实例作为 body 传给 Response 对象。
这会自动将用户重定向到该预签名 URL,节省了服务器下载文件再发送给用户的内存、时间和带宽开销。
s3.tsconst response = new Response(s3file);
console.log(response);
Response (0 KB) {
ok: false,
url: "",
status: 302,
statusText: "",
headers: Headers {
"location": "https://<account-id>.r2.cloudflarestorage.com/...",
},
redirected: true,
bodyUsed: false
}
对兼容 S3 服务的支持
Bun 的 S3 实现支持任何兼容 S3 的存储服务。只需指定对应的 endpoint:
使用 Bun 的 S3Client 连接 AWS S3
AWS S3 是默认选项。你可传入 region 代替 endpoint 以使用 AWS S3。
s3.tsimport { S3Client } from "bun";
// AWS S3
const s3 = new S3Client({
accessKeyId: "access-key",
secretAccessKey: "secret-key",
bucket: "my-bucket",
// endpoint: "https://s3.us-east-1.amazonaws.com",
// region: "us-east-1",
});
使用 Bun 的 S3Client 连接 Google Cloud Storage
使用 Bun 的 S3 client 连接 Google Cloud Storage,在 S3Client 构造器中将 endpoint 设置为 "https://storage.googleapis.com"。
s3.tsimport { S3Client } from "bun";
// Google Cloud Storage
const gcs = new S3Client({
accessKeyId: "access-key",
secretAccessKey: "secret-key",
bucket: "my-bucket",
endpoint: "https://storage.googleapis.com",
});
使用 Bun 的 S3Client 连接 Cloudflare R2
使用 Bun 的 S3 client 连接 Cloudflare R2,在 S3Client 构造器中将 endpoint 设置为包含你的账号 ID 的 R2 端点。
s3.tsimport { S3Client } from "bun";
// CloudFlare R2
const r2 = new S3Client({
accessKeyId: "access-key",
secretAccessKey: "secret-key",
bucket: "my-bucket",
endpoint: "https://<account-id>.r2.cloudflarestorage.com",
});
使用 Bun 的 S3Client 连接 DigitalOcean Spaces
使用 Bun 的 S3 client 连接 DigitalOcean Spaces,在 S3Client 构造器中将 endpoint 设置为对应区域的 DigitalOcean Spaces 端点。
s3.tsimport { S3Client } from "bun";
const spaces = new S3Client({
accessKeyId: "access-key",
secretAccessKey: "secret-key",
bucket: "my-bucket",
// region: "nyc3",
endpoint: "https://<region>.digitaloceanspaces.com",
});
使用 Bun 的 S3Client 连接 MinIO
使用 Bun 的 S3 client 连接 MinIO,在 S3Client 构造器中将 endpoint 设置为 MinIO 运行的 URL。
s3.tsimport { S3Client } from "bun";
const minio = new S3Client({
accessKeyId: "access-key",
secretAccessKey: "secret-key",
bucket: "my-bucket",
// 确保使用正确的 endpoint URL
// 在生产环境中可能不是 localhost!
endpoint: "http://localhost:9000",
});
使用 Bun 的 S3Client 连接 supabase
使用 Bun 的 S3 client 连接 supabase,在 S3Client 构造器中将 endpoint 设置为包含账号 ID 及 /storage/v1/s3 路径的 supabase 端点。确保在 supabase 控制台 https://supabase.com/dashboard/project/<account-id>/settings/storage 中启用 “Enable connection via S3 protocol”,并设置相应区域。
s3.tsimport { S3Client } from "bun";
const supabase = new S3Client({
accessKeyId: "access-key",
secretAccessKey: "secret-key",
bucket: "my-bucket",
region: "us-west-1",
endpoint: "https://<account-id>.supabase.co/storage/v1/s3/storage",
});
使用 Bun 的 S3Client 连接 S3 虚拟主机式端点
使用 S3 虚拟主机式端点时,需要将 virtualHostedStyle 选项设置为 true。
- 如果不指定 endpoint,Bun 会根据 region 和 bucket 自动确定 AWS S3 端点。
- 如果不指定 region,Bun 默认使用 us-east-1。
- 如果明确指定 endpoint,则无需指定 bucket 名称。
s3.tsimport { S3Client } from "bun";
// 从 region 和 bucket 推断的 AWS S3 端点
const s3 = new S3Client({
accessKeyId: "access-key",
secretAccessKey: "secret-key",
bucket: "my-bucket",
virtualHostedStyle: true,
// endpoint: "https://my-bucket.s3.us-east-1.amazonaws.com",
// region: "us-east-1",
});
// AWS S3 指定 endpoint
const s3WithEndpoint = new S3Client({
accessKeyId: "access-key",
secretAccessKey: "secret-key",
endpoint: "https://<bucket-name>.s3.<region>.amazonaws.com",
virtualHostedStyle: true,
});
// Cloudflare R2 指定 endpoint
const r2WithEndpoint = new S3Client({
accessKeyId: "access-key",
secretAccessKey: "secret-key",
endpoint: "https://<bucket-name>.<account-id>.r2.cloudflarestorage.com",
virtualHostedStyle: true,
});
使用 S3 时,凭据是最难处理的部分之一。默认情况下,Bun 会读取以下用于凭据的环境变量。
| 选项名称 | 环境变量 |
|---|
accessKeyId | S3_ACCESS_KEY_ID |
secretAccessKey | S3_SECRET_ACCESS_KEY |
region | S3_REGION |
endpoint | S3_ENDPOINT |
bucket | S3_BUCKET |
sessionToken | S3_SESSION_TOKEN |
如果未设置 S3_* 环境变量,Bun 会依次检查对应的 AWS_* 环境变量。
| 选项名称 | 备用环境变量 |
|---|
accessKeyId | AWS_ACCESS_KEY_ID |
secretAccessKey | AWS_SECRET_ACCESS_KEY |
region | AWS_REGION |
endpoint | AWS_ENDPOINT |
bucket | AWS_BUCKET |
sessionToken | AWS_SESSION_TOKEN |
这些环境变量可以从 .env 文件 或初始化时的进程环境读取(不会使用 process.env)。
你传给 s3.file(credentials)、new Bun.S3Client(credentials) 或其他接收凭据的方法的选项会覆盖默认值。举例来说,如果不同的桶使用相同凭据,你仅需在 .env 中设置凭据一次,然后调用 s3.file() 时只传 bucket: "my-bucket",无需重复所有凭据。
S3Client 对象
当你不使用环境变量或使用多个桶时,可创建 S3Client 对象来显式设置凭据。
s3.tsimport { S3Client } from "bun";
const client = new S3Client({
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
bucket: "my-bucket",
// sessionToken: "..."
endpoint: "https://s3.us-east-1.amazonaws.com",
// endpoint: "https://<account-id>.r2.cloudflarestorage.com", // Cloudflare R2
// endpoint: "http://localhost:9000", // MinIO
});
// 使用 Response 写入
await file.write(new Response("Hello World!"));
// 预签名 URL
const url = file.presign({
expiresIn: 60 * 60 * 24, // 1 天
acl: "public-read",
});
// 删除文件
await file.delete();
S3Client.prototype.write
向 S3 上传或写入文件,可调用 S3Client 实例的 write 方法。
s3.tsconst client = new Bun.S3Client({
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
endpoint: "https://s3.us-east-1.amazonaws.com",
bucket: "my-bucket",
});
await client.write("my-file.txt", "Hello World!");
await client.write("my-file.txt", new Response("Hello World!"));
// 等价于
// await client.file("my-file.txt").write("Hello World!");
S3Client.prototype.delete
删除 S3 文件,调用 S3Client 实例的 delete 方法。
s3.tsconst client = new Bun.S3Client({
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
bucket: "my-bucket",
});
await client.delete("my-file.txt");
// 等价于
// await client.file("my-file.txt").delete();
S3Client.prototype.exists
检查 S3 文件是否存在,调用 S3Client 实例的 exists 方法。
s3.tsconst client = new Bun.S3Client({
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
bucket: "my-bucket",
});
const exists = await client.exists("my-file.txt");
// 等价于
// const exists = await client.file("my-file.txt").exists();
S3File
S3File 实例通过调用 S3Client 的实例方法或 s3.file() 函数创建。类似 Bun.file(),S3File 实例是惰性创建的。它们不一定指向创建时已存在的文件。因此,所有不涉及网络请求的方法都是完全同步的。
Type Referenceinterface S3File extends Blob {
slice(start: number, end?: number): S3File;
exists(): Promise<boolean>;
unlink(): Promise<void>;
presign(options: S3Options): string;
text(): Promise<string>;
json(): Promise<any>;
bytes(): Promise<Uint8Array>;
arrayBuffer(): Promise<ArrayBuffer>;
stream(options: S3Options): ReadableStream;
write(
data: string | Uint8Array | ArrayBuffer | Blob | ReadableStream | Response | Request,
options?: BlobPropertyBag,
): Promise<number>;
exists(options?: S3Options): Promise<boolean>;
unlink(options?: S3Options): Promise<void>;
delete(options?: S3Options): Promise<void>;
presign(options?: S3Options): string;
stat(options?: S3Options): Promise<S3Stat>;
/**
* 由于需要网络请求,大小无法同步获取。
*
* @deprecated 请使用 `stat()` 替代。
*/
size: NaN;
// …为简洁起见省略部分内容
}
和 Bun.file() 一样,S3File 继承自 Blob,因此所有 Blob 上可用的方法也适用于 S3File。读取本地文件数据同样的 API 也适用于从 S3 读取数据。
| 方法 | 输出类型 |
|---|
await s3File.text() | string |
await s3File.bytes() | Uint8Array |
await s3File.json() | JSON |
await s3File.stream() | ReadableStream |
await s3File.arrayBuffer() | ArrayBuffer |
这意味着将 S3File 实例与 fetch()、Response 以及其他接受 Blob 实例的 Web API 一起使用可以开箱即用。
使用 slice 部分读取
要读取文件的部分范围,可使用 slice 方法。
s3.tsconst partial = s3file.slice(0, 1024);
// 将部分范围以 Uint8Array 读取
const bytes = await partial.bytes();
// 将部分范围以字符串读取
const text = await partial.text();
内部通过 HTTP 的 Range 头部请求你想要的字节。此 slice 方法与 Blob.prototype.slice 相同。
从 S3 删除文件
要删除 S3 文件,可以使用 delete 方法。
s3.tsawait s3file.delete();
// await s3File.unlink();
delete 与 unlink 同义。
错误代码
当 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" 的 Error。
S3Client 静态方法
S3Client 类提供了多个静态方法用于操作 S3。
静态方法 S3Client.write
直接写入数据到存储桶的路径,可使用静态方法 S3Client.write。
s3.tsimport { S3Client } from "bun";
const credentials = {
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
bucket: "my-bucket",
// endpoint: "https://s3.us-east-1.amazonaws.com",
// endpoint: "https://<account-id>.r2.cloudflarestorage.com", // Cloudflare R2
};
// 写入字符串
await S3Client.write("my-file.txt", "Hello World");
// 指定类型写入 JSON
await S3Client.write("data.json", JSON.stringify({ hello: "world" }), {
...credentials,
type: "application/json",
});
// fetch 后写入
const res = await fetch("https://example.com/data");
await S3Client.write("data.bin", res, credentials);
// 写入并设置 ACL
await S3Client.write("public.html", html, {
...credentials,
acl: "public-read",
type: "text/html",
});
这等价于调用 new S3Client(credentials).write("my-file.txt", "Hello World")。
静态方法 S3Client.presign
生成 S3 文件预签名 URL,可使用静态方法 S3Client.presign。
s3.tsimport { S3Client } from "bun";
const credentials = {
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
bucket: "my-bucket",
// endpoint: "https://s3.us-east-1.amazonaws.com",
// endpoint: "https://<account-id>.r2.cloudflarestorage.com", // Cloudflare R2
};
const url = S3Client.presign("my-file.txt", {
...credentials,
expiresIn: 3600,
});
这等价于调用 new S3Client(credentials).presign("my-file.txt", { expiresIn: 3600 })。
静态方法 S3Client.list
列出存储桶中的部分或所有(最多 1000 个)对象,使用静态方法 S3Client.list。
s3.tsimport { S3Client } from "bun";
const credentials = {
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
bucket: "my-bucket",
// endpoint: "https://s3.us-east-1.amazonaws.com",
// endpoint: "https://<account-id>.r2.cloudflarestorage.com", // Cloudflare R2
};
// 列出最多 1000 个存储桶中的对象
const allObjects = await S3Client.list(null, credentials);
// 列出 `uploads/` 前缀下最多 500 个对象,并获取所有者字段
const uploads = await S3Client.list({
prefix: 'uploads/',
maxKeys: 500,
fetchOwner: true,
}, credentials);
// 检查是否有更多结果
if (uploads.isTruncated) {
// 列出下一批 `uploads/` 下的对象
const moreUploads = await S3Client.list({
prefix: 'uploads/',
maxKeys: 500,
startAfter: uploads.contents!.at(-1).key,
fetchOwner: true,
}, credentials);
}
这等价于调用 new S3Client(credentials).list()。
静态方法 S3Client.exists
检查 S3 文件是否存在,使用静态方法 S3Client.exists。
s3.tsimport { S3Client } from "bun";
const credentials = {
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
bucket: "my-bucket",
// endpoint: "https://s3.us-east-1.amazonaws.com",
// endpoint: "https://<account-id>.r2.cloudflarestorage.com", // Cloudflare R2
};
const exists = await S3Client.exists("my-file.txt", credentials);
同样方法也适用于 S3File 实例。
s3.tsimport { s3 } from "bun";
const s3file = s3.file("my-file.txt", {
// ...credentials,
});
const exists = await s3file.exists();
静态方法 S3Client.size
如果不下载即可检查 S3 文件的大小,可以使用静态方法 S3Client.size。
s3.tsimport { S3Client } from "bun";
const credentials = {
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
bucket: "my-bucket",
// endpoint: "https://s3.us-east-1.amazonaws.com",
// endpoint: "https://<account-id>.r2.cloudflarestorage.com", // Cloudflare R2
};
const bytes = await S3Client.size("my-file.txt", credentials);
这等价于调用 new S3Client(credentials).size("my-file.txt")。
静态方法 S3Client.stat
获取 S3 文件的大小、etag 和其他元数据,使用静态方法 S3Client.stat。
s3.tsimport { S3Client } from "bun";
const credentials = {
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
bucket: "my-bucket",
// endpoint: "https://s3.us-east-1.amazonaws.com",
// endpoint: "https://<account-id>.r2.cloudflarestorage.com", // Cloudflare R2
};
const stat = await S3Client.stat("my-file.txt", credentials);
{
etag: "\"7a30b741503c0b461cc14157e2df4ad8\"",
lastModified: 2025-01-07T00:19:10.000Z,
size: 1024,
type: "text/plain;charset=utf-8",
}
静态方法 S3Client.delete
删除 S3 文件,使用静态方法 S3Client.delete。
s3.tsimport { S3Client } from "bun";
const credentials = {
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
bucket: "my-bucket",
// endpoint: "https://s3.us-east-1.amazonaws.com",
};
await S3Client.delete("my-file.txt", credentials);
// 等价于
// await new S3Client(credentials).delete("my-file.txt");
// S3Client.unlink 是 S3Client.delete 的别名
await S3Client.unlink("my-file.txt", credentials);
s3:// 协议
为了方便本地文件和 S3 文件复用同样的代码,s3:// 协议在 fetch 和 Bun.file() 中得到支持。
s3.tsconst response = await fetch("s3://my-bucket/my-file.txt");
const file = Bun.file("s3://my-bucket/my-file.txt");
你还可以给 fetch 和 Bun.file 传递 s3 选项。
s3.tsconst response = await fetch("s3://my-bucket/my-file.txt", {
s3: {
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
endpoint: "https://s3.us-east-1.amazonaws.com",
},
headers: {
range: "bytes=0-1023",
},
});
UTF-8、UTF-16 和 BOM(字节顺序标记)
跟 Response 和 Blob 一样,S3File 默认假定为 UTF-8 编码。
调用 S3File 的 text() 或 json() 方法时:
- 如果检测到 UTF-16 字节顺序标记(BOM),则按 UTF-16 处理。JavaScriptCore 原生支持 UTF-16,因此跳过 UTF-8 转码过程(并剥离 BOM)。这通常很好,但如果 UTF-16 字符中有无效代理对,则会传递给 JavaScriptCore(与源码情况相同)。
- 如果检测到 UTF-8 BOM,则在传给 JavaScriptCore 前剥离 BOM,并将无效的 UTF-8 代码点替换为 Unicode 替代字符 (
\uFFFD)。
- 不支持 UTF-32。