Skip to content

Servidores de produção frequentemente leem, fazem upload e escrevem arquivos em serviços de armazenamento de objetos compatíveis com S3 em vez do sistema de arquivos local. Historicamente, isso significa que APIs de sistema de arquivos locais que você usa em desenvolvimento não podem ser usadas em produção. Quando você usa o Bun, as coisas são diferentes.

A API S3 do Bun é rápida

O Bun fornece bindings nativos rápidos para interagir com serviços de armazenamento de objetos compatíveis com S3. A API S3 do Bun é projetada para ser simples e sentir similar às APIs Response e Blob do fetch (como as APIs de sistema de arquivos locais do Bun).

ts
import { s3, write, S3Client } from "bun";

// Bun.s3 lê variáveis de ambiente para credenciais
// file() retorna uma referência lazy para um arquivo no S3
const metadata = s3.file("123.json");

// Download do S3 como JSON
const data = await metadata.json();

// Upload para o S3
await write(metadata, JSON.stringify({ name: "John", age: 30 }));

// Presign de uma URL (síncrono - sem requisição de rede necessária)
const url = metadata.presign({
  acl: "public-read",
  expiresIn: 60 * 60 * 24, // 1 dia
});

// Deleta o arquivo
await metadata.delete();

S3 é o padrão de fato de sistema de arquivos da internet. A API S3 do Bun funciona com serviços de armazenamento compatíveis com S3 como:

  • AWS S3
  • Cloudflare R2
  • DigitalOcean Spaces
  • MinIO
  • Backblaze B2
  • ...e qualquer outro serviço de armazenamento compatível com S3

Uso Básico

Existem várias maneiras de interagir com a API S3 do Bun.

Bun.S3Client e Bun.s3

Bun.s3 é equivalente a new Bun.S3Client(), confiando em variáveis de ambiente para credenciais.

Para definir credenciais explicitamente, passe-as para o construtor Bun.S3Client.

ts
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 é um singleton global que é equivalente a `new Bun.S3Client()`

Trabalhando com Arquivos S3

O método file em S3Client retorna uma referência lazy para um arquivo no S3.

ts
// Uma referência lazy para um arquivo no S3
const s3file: S3File = client.file("123.json");

Como Bun.file(path), o método file do S3Client é síncrono. Ele não faz zero requisições de rede até que você chame um método que depende de uma requisição de rede.

Lendo arquivos do S3

Se você já usou a API fetch, você está familiarizado com as APIs Response e Blob. S3File estende Blob. Os mesmos métodos que funcionam em Blob também funcionam em S3File.

ts
// Lê um S3File como texto
const text = await s3file.text();

// Lê um S3File como JSON
const json = await s3file.json();

// Lê um S3File como ArrayBuffer
const buffer = await s3file.arrayBuffer();

// Obtém apenas os primeiros 1024 bytes
const partial = await s3file.slice(0, 1024).text();

// Faz stream do arquivo
const stream = s3file.stream();
for await (const chunk of stream) {
  console.log(chunk);
}

Otimização de memória

Métodos como text(), json(), bytes(), ou arrayBuffer() evitam duplicar a string ou bytes na memória quando possível.

Se o texto for ASCII, o Bun transfere diretamente a string para o JavaScriptCore (o engine) sem transcodificação e sem duplicar a string na memória. Quando você usa .bytes() ou .arrayBuffer(), ele também evita duplicar os bytes na memória.

Estes métodos auxiliares não apenas simplificam a API, eles também a tornam mais rápida.

Escrevendo e fazendo upload de arquivos para o S3

Escrever no S3 é igualmente simples.

ts
// Escreve uma string (substituindo o arquivo)
await s3file.write("Hello World!");

// Escreve um Buffer (substituindo o arquivo)
await s3file.write(Buffer.from("Hello World!"));

// Escreve uma Response (substituindo o arquivo)
await s3file.write(new Response("Hello World!"));

// Escreve com content type
await s3file.write(JSON.stringify({ name: "John", age: 30 }), {
  type: "application/json",
});

// Escreve usando um writer (streaming)
const writer = s3file.writer({ type: "application/json" });
writer.write("Hello");
writer.write(" World!");
await writer.end();

// Escreve usando Bun.write
await Bun.write(s3file, "Hello World!");

Trabalhando com arquivos grandes (streams)

O Bun automaticamente gerencia uploads multipart para arquivos grandes e fornece capacidades de streaming. A mesma API que funciona para arquivos locais também funciona para arquivos S3.

ts
// Escreve um arquivo grande
const bigFile = Buffer.alloc(10 * 1024 * 1024); // 10MB
const writer = s3file.writer({
  // Automaticamente retry em erros de rede até 3 vezes
  retry: 3,

  // Enfileira até 10 requisições por vez
  queueSize: 10,

  // Upload em chunks de 5 MB
  partSize: 5 * 1024 * 1024,
});
for (let i = 0; i < 10; i++) {
  writer.write(bigFile);
  await writer.flush();
}
await writer.end();

Presign de URLs

Quando seu serviço de produção precisa permitir que usuários façam upload de arquivos para seu servidor, é frequentemente mais confiável para o usuário fazer upload diretamente para o S3 em vez de seu servidor atuar como um intermediário.

Para facilitar isso, você pode presign URLs para arquivos S3. Isto gera uma URL com uma assinatura que permite a um usuário fazer upload com segurança daquele arquivo específico para o S3, sem expor suas credenciais ou conceder acesso desnecessário ao seu bucket.

O comportamento padrão é gerar uma URL GET que expira em 24 horas. O Bun tenta inferir o content type da extensão do arquivo. Se a inferência não for possível, ele usará application/octet-stream como padrão.

ts
import { s3 } from "bun";

// Gera uma URL presigned que expira em 24 horas (padrão)
const download = s3.presign("my-file.txt"); // GET, text/plain, expira em 24 horas

const upload = s3.presign("my-file", {
  expiresIn: 3600, // 1 hora
  method: "PUT",
  type: "application/json", // Sem extensão para inferir, então podemos especificar o content type como JSON
});

// Você pode chamar .presign() se tiver uma referência de arquivo, mas evite fazer isso
// a menos que você já tenha uma referência (para evitar uso de memória).
const myFile = s3.file("my-file.txt");
const presignedFile = myFile.presign({
  expiresIn: 3600, // 1 hora
});

Definindo ACLs

Para definir uma ACL (access control list) em uma URL presigned, passe a opção acl:

ts
const url = s3file.presign({
  acl: "public-read",
  expiresIn: 3600,
});

Você pode passar qualquer uma das seguintes ACLs:

ACLExplicação
"public-read"O objeto é legível pelo público.
"private"O objeto é legível apenas pelo proprietário do bucket.
"public-read-write"O objeto é legível e gravável pelo público.
"authenticated-read"O objeto é legível pelo proprietário do bucket e usuários autenticados.
"aws-exec-read"O objeto é legível pela conta AWS que fez a requisição.
"bucket-owner-read"O objeto é legível pelo proprietário do bucket.
"bucket-owner-full-control"O objeto é legível e gravável pelo proprietário do bucket.
"log-delivery-write"O objeto é gravável por serviços AWS usados para entrega de logs.

URLs com Expiração

Para definir um tempo de expiração para uma URL presigned, passe a opção expiresIn.

ts
const url = s3file.presign({
  // Segundos
  expiresIn: 3600, // 1 hora

  // access control list
  acl: "public-read",

  // método HTTP
  method: "PUT",
});

method

Para definir o método HTTP para uma URL presigned, passe a opção method.

ts
const url = s3file.presign({
  method: "PUT",
  // method: "DELETE",
  // method: "GET",
  // method: "HEAD",
  // method: "POST",
  // method: "PUT",
});

new Response(S3File)

Para redirecionar rapidamente usuários para uma URL presigned de um arquivo S3, passe uma instância S3File para um objeto Response como body.

Isto redirecionará automaticamente o usuário para a URL presigned do arquivo S3, economizando o custo de memória, tempo e largura de banda de baixar o arquivo para seu servidor e enviá-lo de volta ao usuário.

ts
const response = new Response(s3file);
console.log(response);
txt
Response (0 KB) {
  ok: false,
  url: "",
  status: 302,
  statusText: "",
  headers: Headers {
    "location": "https://<account-id>.r2.cloudflarestorage.com/...",
  },
  redirected: true,
  bodyUsed: false
}

Suporte para Serviços Compatíveis com S3

A implementação S3 do Bun funciona com qualquer serviço de armazenamento compatível com S3. Basta especificar o endpoint apropriado:

Usando Bun's S3Client com AWS S3

AWS S3 é o padrão. Você também pode passar uma opção region em vez de uma opção endpoint para AWS S3.

ts
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",
});

Usando Bun's S3Client com Google Cloud Storage

Para usar o cliente S3 do Bun com Google Cloud Storage, defina endpoint como "https://storage.googleapis.com" no construtor S3Client.

ts
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",
});

Usando Bun's S3Client com Cloudflare R2

Para usar o cliente S3 do Bun com Cloudflare R2, defina endpoint como o endpoint R2 no construtor S3Client. O endpoint R2 inclui seu ID de conta.

ts
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",
});

Usando Bun's S3Client com DigitalOcean Spaces

Para usar o cliente S3 do Bun com DigitalOcean Spaces, defina endpoint como o endpoint DigitalOcean Spaces no construtor S3Client.

ts
import { S3Client } from "bun";

const spaces = new S3Client({
  accessKeyId: "access-key",
  secretAccessKey: "secret-key",
  bucket: "my-bucket",
  // region: "nyc3",
  endpoint: "https://<region>.digitaloceanspaces.com",
});

Usando Bun's S3Client com MinIO

Para usar o cliente S3 do Bun com MinIO, defina endpoint como a URL em que o MinIO está rodando no construtor S3Client.

ts
import { S3Client } from "bun";

const minio = new S3Client({
  accessKeyId: "access-key",
  secretAccessKey: "secret-key",
  bucket: "my-bucket",

  // Certifique-se de usar a URL de endpoint correta
  // Pode não ser localhost em produção!
  endpoint: "http://localhost:9000",
});

Usando Bun's S3Client com supabase

Para usar o cliente S3 do Bun com supabase, defina endpoint como o endpoint supabase no construtor S3Client. O endpoint supabase inclui seu ID de conta e o caminho /storage/v1/s3. Certifique-se de definir Enable connection via S3 protocol no dashboard supabase em https://supabase.com/dashboard/project/<account-id>/settings/storage e definir a região informada na mesma seção.

ts
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",
});

Usando Bun's S3Client com endpoints S3 Virtual Hosted-Style

Ao usar um endpoint S3 Virtual Hosted-Style, você precisa definir a opção virtualHostedStyle como true.

NOTE

- Se você não especificar um endpoint, o Bun automaticamente determinará o endpoint AWS S3 usando a região e bucket fornecidos. - Se nenhuma região for especificada, o Bun usa us-east-1 como padrão. - Se você fornecer explicitamente um endpoint, não precisa especificar um nome de bucket.
ts
import { S3Client } from "bun";

// Endpoint AWS S3 inferido da região e 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, 
});

Credenciais

Credenciais são uma das partes mais difíceis de usar S3, e tentamos tornar o mais fácil possível. Por padrão, o Bun lê as seguintes variáveis de ambiente para credenciais.

Nome da opçãoVariável de ambiente
accessKeyIdS3_ACCESS_KEY_ID
secretAccessKeyS3_SECRET_ACCESS_KEY
regionS3_REGION
endpointS3_ENDPOINT
bucketS3_BUCKET
sessionTokenS3_SESSION_TOKEN

Se a variável de ambiente S3_* não estiver definida, o Bun também verificará a variável de ambiente AWS_* para cada uma das opções acima.

Nome da opçãoVariável de ambiente fallback
accessKeyIdAWS_ACCESS_KEY_ID
secretAccessKeyAWS_SECRET_ACCESS_KEY
regionAWS_REGION
endpointAWS_ENDPOINT
bucketAWS_BUCKET
sessionTokenAWS_SESSION_TOKEN

Estas variáveis de ambiente são lidas de arquivos .env ou do ambiente do processo no momento da inicialização (process.env não é usado para isso).

Estes padrões são sobrescritos pelas opções que você passa para s3.file(credentials), new Bun.S3Client(credentials), ou qualquer um dos métodos que aceitam credenciais. Então se, por exemplo, você usa as mesmas credenciais para diferentes buckets, você pode definir as credenciais uma vez no seu arquivo .env e então passar bucket: "my-bucket" para a função s3.file() sem ter que especificar todas as credenciais novamente.

Objetos S3Client

Quando você não está usando variáveis de ambiente ou usando múltiplos buckets, você pode criar um objeto S3Client para definir credenciais explicitamente.

ts
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
});

// Escreve usando uma Response
await file.write(new Response("Hello World!"));

// Presign de uma URL
const url = file.presign({
  expiresIn: 60 * 60 * 24, // 1 dia
  acl: "public-read",
});

// Deleta o arquivo
await file.delete();

S3Client.prototype.write

Para fazer upload ou escrever um arquivo no S3, chame write na instância S3Client.

ts
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!"));

// equivalente a
// await client.file("my-file.txt").write("Hello World!");

S3Client.prototype.delete

Para deletar um arquivo do S3, chame delete na instância S3Client.

ts
const client = new Bun.S3Client({
  accessKeyId: "your-access-key",
  secretAccessKey: "your-secret-key",
  bucket: "my-bucket",
});

await client.delete("my-file.txt");
// equivalente a
// await client.file("my-file.txt").delete();

S3Client.prototype.exists

Para verificar se um arquivo existe no S3, chame exists na instância S3Client.

ts
const client = new Bun.S3Client({
  accessKeyId: "your-access-key",
  secretAccessKey: "your-secret-key",
  bucket: "my-bucket",
});

const exists = await client.exists("my-file.txt");
// equivalente a
// const exists = await client.file("my-file.txt").exists();

S3File

Instâncias S3File são criadas chamando o método de instância S3Client ou a função s3.file(). Como Bun.file(), instâncias S3File são lazy. Elas não se referem a algo que necessariamente existe no momento da criação. É por isso que todos os métodos que não envolvem requisições de rede são totalmente síncronos.

ts
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 não está disponível sincronamente porque requer uma requisição de rede.
   *
   * @deprecated Use `stat()` em vez disso.
   */
  size: NaN;

  // ... mais omitido por brevidade
}

Como Bun.file(), S3File estende Blob, então todos os métodos disponíveis em Blob também estão disponíveis em S3File. A mesma API para ler dados de um arquivo local também está disponível para ler dados do S3.

MétodoSaída
await s3File.text()string
await s3File.bytes()Uint8Array
await s3File.json()JSON
await s3File.stream()ReadableStream
await s3File.arrayBuffer()ArrayBuffer

Isso significa que usar instâncias S3File com fetch(), Response, e outras web APIs que aceitam instâncias Blob simplesmente funciona.

Leituras parciais com slice

Para ler um intervalo parcial de um arquivo, você pode usar o método slice.

ts
const partial = s3file.slice(0, 1024);

// Lê o intervalo parcial como Uint8Array
const bytes = await partial.bytes();

// Lê o intervalo parcial como string
const text = await partial.text();

Internamente, isto funciona usando o header HTTP Range para requisitar apenas os bytes que você quer. Este método slice é o mesmo que Blob.prototype.slice.

Deletando arquivos do S3

Para deletar um arquivo do S3, você pode usar o método delete.

ts
await s3file.delete();
// await s3File.unlink();

delete é o mesmo que unlink.

Códigos de erro

Quando a API S3 do Bun lança um erro, ele terá uma propriedade code que corresponde a um dos seguintes valores:

  • 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

Quando o serviço S3 Object Storage retorna um erro (ou seja, não o Bun), será uma instância S3Error (uma instância Error com o nome "S3Error").

Métodos estáticos S3Client

A classe S3Client fornece vários métodos estáticos para interagir com o S3.

S3Client.write (estático)

Para escrever dados diretamente em um caminho no bucket, você pode usar o método estático S3Client.write.

ts
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
};

// Escreve string
await S3Client.write("my-file.txt", "Hello World");

// Escreve JSON com type
await S3Client.write("data.json", JSON.stringify({ hello: "world" }), {
  ...credentials,
  type: "application/json",
});

// Escreve de fetch
const res = await fetch("https://example.com/data");
await S3Client.write("data.bin", res, credentials);

// Escreve com ACL
await S3Client.write("public.html", html, {
  ...credentials,
  acl: "public-read",
  type: "text/html",
});

Isto é equivalente a chamar new S3Client(credentials).write("my-file.txt", "Hello World").

S3Client.presign (estático)

Para gerar uma URL presigned para um arquivo S3, você pode usar o método estático S3Client.presign.

ts
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,
});

Isto é equivalente a chamar new S3Client(credentials).presign("my-file.txt", { expiresIn: 3600 }).

S3Client.list (estático)

Para listar alguns ou todos (até 1.000) objetos em um bucket, você pode usar o método estático S3Client.list.

ts
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
};

// Lista (até) 1000 objetos no bucket
const allObjects = await S3Client.list(null, credentials);

// Lista (até) 500 objetos sob o prefixo `uploads/`, com campo owner para cada objeto
const uploads = await S3Client.list({
  prefix: 'uploads/',
  maxKeys: 500,
  fetchOwner: true,
}, credentials);

// Verifica se mais resultados estão disponíveis
if (uploads.isTruncated) {
  // Lista próximo lote de objetos sob o prefixo `uploads/`
  const moreUploads = await S3Client.list({
    prefix: 'uploads/',
    maxKeys: 500,
    startAfter: uploads.contents!.at(-1).key
    fetchOwner: true,
  }, credentials);
}

Isto é equivalente a chamar new S3Client(credentials).list().

S3Client.exists (estático)

Para verificar se um arquivo S3 existe, você pode usar o método estático S3Client.exists.

ts
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);

O mesmo método também funciona em instâncias S3File.

ts
import { s3 } from "bun";

const s3file = s3.file("my-file.txt", {
  // ...credentials,
});

const exists = await s3file.exists();

S3Client.size (estático)

Para verificar rapidamente o tamanho de um arquivo S3 sem baixá-lo, você pode usar o método estático S3Client.size.

ts
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);

Isto é equivalente a chamar new S3Client(credentials).size("my-file.txt").

S3Client.stat (estático)

Para obter o tamanho, etag e outros metadados de um arquivo S3, você pode usar o método estático S3Client.stat.

ts
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);
txt
{
  etag: "\"7a30b741503c0b461cc14157e2df4ad8\"",
  lastModified: 2025-01-07T00:19:10.000Z,
  size: 1024,
  type: "text/plain;charset=utf-8",
}

S3Client.delete (estático)

Para deletar um arquivo S3, você pode usar o método estático S3Client.delete.

ts
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);
// equivalente a
// await new S3Client(credentials).delete("my-file.txt");

// S3Client.unlink é alias de S3Client.delete
await S3Client.unlink("my-file.txt", credentials);

Protocolo s3://

Para facilitar o uso do mesmo código para arquivos locais e arquivos S3, o protocolo s3:// é suportado em fetch e Bun.file().

ts
const response = await fetch("s3://my-bucket/my-file.txt");
const file = Bun.file("s3://my-bucket/my-file.txt");

Você pode adicionalmente passar opções s3 para as funções fetch e Bun.file.

ts
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 e BOM (byte order mark)

Como Response e Blob, S3File assume encoding UTF-8 por padrão.

Ao chamar um dos métodos text() ou json() em um S3File:

  • Quando um byte order mark (BOM) UTF-16 é detectado, ele será tratado como UTF-16. O JavaScriptCore suporta nativamente UTF-16, então ele pula o processo de transcodificação UTF-8 (e remove o BOM). Isto é principalmente bom, mas significa que se você tiver caracteres de surrogate pairs inválidos na sua string UTF-16, eles serão passados para o JavaScriptCore (mesmo que código fonte).
  • Quando um BOM UTF-8 é detectado, ele é removido antes da string ser passada para o JavaScriptCore e codepoints UTF-8 inválidos são substituídos pelo caractere de substituição Unicode (\uFFFD).
  • UTF-32 não é suportado.

Bun by www.bunjs.com.cn edit