Продакшн-серверы часто читают, загружают и записывают файлы в S3-совместимые объектные хранилища вместо локальной файловой системы. Исторически это означает, что API локальной файловой системы, которые вы используете в разработке, не могут использоваться в продакшене. Когда вы используете Bun, всё по-другому.
S3 API Bun быстрый
Bun предоставляет быстрые нативные привязки для взаимодействия с S3-совместимыми объектными хранилищами. S3 API Bun разработан быть простым и похожим на Response и Blob API fetch (как и API локальной файловой системы Bun).
import { 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 }));
// Presign URL (синхронно - сетевой запрос не нужен)
const url = metadata.presign({
acl: "public-read",
expiresIn: 60 * 60 * 24, // 1 день
});
// Удалить файл
await metadata.delete();S3 — это фактический стандарт интернет-файловой системы. S3 API Bun работает с S3-совместимыми хранилищами, такими как:
- AWS S3
- Cloudflare R2
- DigitalOcean Spaces
- MinIO
- Backblaze B2
- ...и любое другое S3-совместимое хранилище
Базовое использование
Есть несколько способов взаимодействия с S3 API Bun.
Bun.S3Client и Bun.s3
Bun.s3 эквивалентен new Bun.S3Client(), полагаясь на переменные окружения для учётных данных.
Чтобы явно установить учётные данные, передайте их конструктору Bun.S3Client.
import { 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 — это глобальный singleton, эквивалентный `new Bun.S3Client()`Работа с S3-файлами
Метод file в S3Client возвращает ленивую ссылку на файл в S3.
// Ленивая ссылка на файл в S3
const s3file: S3File = client.file("123.json");Как и Bun.file(path), метод file в S3Client синхронен. Он не выполняет никаких сетевых запросов, пока вы не вызовете метод, который зависит от сетевого запроса.
Чтение файлов из S3
Если вы использовали fetch API, вы знакомы с Response и Blob API. S3File расширяет Blob. Те же методы, которые работают с Blob, также работают с S3File.
// Прочитать 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 так же проста.
// Записать строку (заменяя файл)
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",
});
// Записать используя 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-файлов.
// Записать большой файл
const bigFile = Buffer.alloc(10 * 1024 * 1024); // 10MB
const writer = s3file.writer({
// Автоматически повторять при сетевых ошибках до 3 раз
retry: 3,
// Очередить до 10 запросов одновременно
queueSize: 10,
// Загружать частями по 5 MB
partSize: 5 * 1024 * 1024,
});
for (let i = 0; i < 10; i++) {
writer.write(bigFile);
await writer.flush();
}
await writer.end();Presigning URL
Когда вашему продакшн-сервису нужно позволить пользователям загружать файлы на ваш сервер, часто надёжнее для пользователя загружать напрямую в S3 вместо того, чтобы ваш сервер выступал посредником.
Для этого вы можете presign URL для S3-файлов. Это генерирует URL с подписью, который позволяет пользователю безопасно загружать этот конкретный файл в S3, не раскрывая ваши учётные данные и не предоставляя им ненужный доступ к вашему бакету.
Поведение по умолчанию — генерировать GET URL, который истекает через 24 часа. Bun пытается определить тип контента из расширения файла. Если определение невозможно, по умолчанию используется application/octet-stream.
import { s3 } from "bun";
// Сгенерировать presigned URL, который истекает через 24 часа (по умолчанию)
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", // Нет расширения для определения, поэтому можем указать тип контента как JSON
});
// Вы можете вызвать .presign() на ссылке на файл, но избегайте этого
// если у вас ещё нет ссылки (чтобы избежать использования памяти).
const myFile = s3.file("my-file.txt");
const presignedFile = myFile.presign({
expiresIn: 3600, // 1 час
});Установка ACL
Чтобы установить ACL (список управления доступом) на presigned URL, передайте опцию acl:
const 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
Чтобы установить время истечения для presigned URL, передайте опцию expiresIn.
const url = s3file.presign({
// Секунды
expiresIn: 3600, // 1 час
// список управления доступом
acl: "public-read",
// HTTP метод
method: "PUT",
});method
Чтобы установить HTTP-метод для presigned URL, передайте опцию method.
const url = s3file.presign({
method: "PUT",
// method: "DELETE",
// method: "GET",
// method: "HEAD",
// method: "POST",
// method: "PUT",
});new Response(S3File)
Чтобы быстро перенаправить пользователей на presigned URL для S3-файла, передайте экземпляр S3File в объект Response как тело.
Это автоматически перенаправит пользователя на presigned URL для S3-файла, экономя вам память, время и стоимость пропускной способности за скачивание файла на ваш сервер и отправку его обратно пользователю.
const 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-совместимых сервисов
Реализация S3 Bun работает с любым S3-совместимым хранилищем. Просто укажите соответствующую конечную точку:
Использование Bun's S3Client с AWS S3
AWS S3 — по умолчанию. Вы также можете передать опцию region вместо опции endpoint для AWS S3.
import { 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's S3Client с Google Cloud Storage
Чтобы использовать S3-клиент Bun с Google Cloud Storage, установите endpoint в "https://storage.googleapis.com" в конструкторе S3Client.
import { 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's S3Client с Cloudflare R2
Чтобы использовать S3-клиент Bun с Cloudflare R2, установите endpoint в конечную точку R2 в конструкторе S3Client. Конечная точка R2 включает ваш ID аккаунта.
import { 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's S3Client с DigitalOcean Spaces
Чтобы использовать S3-клиент Bun с DigitalOcean Spaces, установите endpoint в конечную точку DigitalOcean Spaces в конструкторе S3Client.
import { S3Client } from "bun";
const spaces = new S3Client({
accessKeyId: "access-key",
secretAccessKey: "secret-key",
bucket: "my-bucket",
// region: "nyc3",
endpoint: "https://<region>.digitaloceanspaces.com",
});Использование Bun's S3Client с MinIO
Чтобы использовать S3-клиент Bun с MinIO, установите endpoint в URL, на котором работает MinIO, в конструкторе S3Client.
import { S3Client } from "bun";
const minio = new S3Client({
accessKeyId: "access-key",
secretAccessKey: "secret-key",
bucket: "my-bucket",
// Убедитесь, что используете правильный URL конечной точки
// В продакшене это может быть не localhost!
endpoint: "http://localhost:9000",
});Использование Bun's S3Client с supabase
Чтобы использовать S3-клиент Bun с supabase, установите endpoint в конечную точку supabase в конструкторе S3Client. Конечная точка supabase включает ID вашего аккаунта и путь /storage/v1/s3. Убедитесь, что включили Enable connection via S3 protocol в панели управления supabase в https://supabase.com/dashboard/project/<account-id>/settings/storage и установили регион, указанный в том же разделе.
import { 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's S3Client с конечными точками S3 Virtual Hosted-Style
При использовании конечной точки S3 Virtual Hosted-Style нужно установить опцию virtualHostedStyle в true.
NOTE
- Если вы не указываете endpoint, Bun автоматически определит конечную точку AWS S3, используя предоставленные region и bucket. - Если region не указан, Bun по умолчанию использует us-east-1. - Если вы явно указываете endpoint, вам не нужно указывать имя bucket.import { S3Client } from "bun";
// Конечная точка AWS S3 выведена из region и bucket
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
const s3WithEndpoint = new S3Client({
accessKeyId: "access-key",
secretAccessKey: "secret-key",
endpoint: "https://<bucket-name>.s3.<region>.amazonaws.com",
virtualHostedStyle: true,
});
// Cloudflare R2
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 файле, а затем передать bucket: "my-bucket" в функцию s3.file() без необходимости указывать все учётные данные снова.
Объекты S3Client
Когда вы не используете переменные окружения или используете несколько бакетов, вы можете создать объект S3Client для явной установки учётных данных.
import { 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!"));
// Presign URL
const url = file.presign({
expiresIn: 60 * 60 * 24, // 1 день
acl: "public-read",
});
// Удалить файл
await file.delete();S3Client.prototype.write
Чтобы загрузить или записать файл в S3, вызовите write на экземпляре S3Client.
const 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, вызовите delete на экземпляре S3Client.
const 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, вызовите exists на экземпляре S3Client.
const 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 ленивы. Они не ссылаются на то, что обязательно существует во время создания. Вот почему все методы, не связанные с сетевыми запросами, полностью синхронны.
interface 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>;
/**
* Size не доступен синхронно, потому что требует сетевого запроса.
*
* @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 и другими веб-API, которые принимают экземпляры Blob, просто работает.
Частичное чтение с slice
Чтобы прочитать частичный диапазон файла, вы можете использовать метод slice.
const 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.
await s3file.delete();
// await s3File.unlink();delete — то же самое, что и unlink.
Коды ошибок
Когда S3 API Bun выбрасывает ошибку, у неё будет свойство code, соответствующее одному из следующих значений:
ERR_S3_MISSING_CREDENTIALSERR_S3_INVALID_METHODERR_S3_INVALID_PATHERR_S3_INVALID_ENDPOINTERR_S3_INVALID_SIGNATUREERR_S3_INVALID_SESSION_TOKEN
Когда сервис S3 Object Storage возвращает ошибку (то есть не Bun), это будет экземпляр S3Error (экземпляр Error с именем "S3Error").
Статические методы S3Client
Класс S3Client предоставляет несколько статических методов для взаимодействия с S3.
S3Client.write (статический)
Чтобы записать данные напрямую в путь в бакете, вы можете использовать статический метод S3Client.write.
import { 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 (статический)
Чтобы сгенерировать presigned URL для S3-файла, вы можете использовать статический метод S3Client.presign.
import { 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。
import { 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.
import { 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.
import { s3 } from "bun";
const s3file = s3.file("my-file.txt", {
// ...credentials,
});
const exists = await s3file.exists();S3Client.size (статический)
Чтобы быстро проверить размер S3-файла без его загрузки, вы можете использовать статический метод S3Client.size.
import { 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 (статический)
Чтобы получить размер, etag и другие метаданные S3-файла, вы можете использовать статический метод S3Client.stat.
import { 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.
import { 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-файлов, fetch и Bun.file() поддерживают протокол s3://.
const response = await fetch("s3://my-bucket/my-file.txt");
const file = Bun.file("s3://my-bucket/my-file.txt");Вы также можете передать опции s3 в функции fetch и Bun.file.
const 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.
При вызове одного из методов text() или json() на S3File:
- При обнаружении байтового порядка UTF-16 (BOM), он будет обработан как UTF-16. JavaScriptCore нативно поддерживает UTF-16, поэтому он пропускает процесс перекодирования UTF-8 (и удаляет BOM). Это в основном хорошо, но это действительно означает, что если в вашей UTF-16 строке есть недопустимые суррогатные пары, они будут переданы в JavaScriptCore (как есть в исходном коде).
- При обнаружении BOM UTF-8, он будет удалён до передачи строки в JavaScriptCore, недопустимые кодовые точки UTF-8 будут заменены на символ замены Unicode (
\uFFFD). - UTF-32 не поддерживается.