Téléversement multipart

Une action "use server" reçoit une Request Web avec le corps multipart ; req.formData() le parse. Les petits corps restent en mémoire ; les corps dépassant le seuil de spool (~1 Mo) utilisent le parseur en streaming via le pont natif __bextReadChunk.

Astuce
N'oubliez pas enctype="multipart/form-data" sur le formulaire — sans lui, le navigateur encode les champs en application/x-www-form-urlencoded et le champ file n'est jamais envoyé. Le seuil de spool (~1 Mo) s'applique à l'ensemble du corps, pas fichier par fichier.

Téléverser un fichier

src/actions/upload.tsTypeScript
// src/actions/upload.ts
"use server";

export async function handleUpload(req: Request): Promise<Response> {
  const form = await req.formData();
  const file = form.get("file") as File | null;
  if (!file) {
    return new Response(null, { status: 303, headers: { Location: "/examples/upload" } });
  }
  // file.name, file.size, file.type are available here.
  // For large files (>1 MB spool threshold) the body is streamed
  // via __bextReadChunk — formData() handles this transparently.
  return new Response(null, {
    status: 303,
    headers: {
      Location: "/examples/upload?ok=1&name=" + encodeURIComponent(file.name)
        + "&size=" + file.size + "&type=" + encodeURIComponent(file.type),
    },
  });
}

// page.tsx — enctype="multipart/form-data" is required for file inputs
<form
  method="post"
  action="/_bext/action/handleUpload"
  enctype="multipart/form-data"
>
  <input type="file" name="file" />
  <input name="note" placeholder="optional note" />
  <button type="submit">upload</button>
</form>