
# Téléversements de fichiers de formulaire

Les formulaires peuvent collecter des fichiers — CV, factures, photos, documents — et les persister dans votre propre stockage plutôt que dans un CDN tiers. Les champs de pièce jointe affichent un sélecteur de fichiers (et une zone de glisser-déposer optionnelle), valident le type et la taille avant le téléversement, montrent la progression et les aperçus, et soumettent un objet de métadonnées canonique `{ url, name, size, mimeType }`. Les fichiers atterrissent dans une destination `app.buckets[]` configurée sur votre stockage S3, disque local ou base de données.

```yaml
buckets:
  - name: applications
    default: true
    backend: s3
    config: { bucket: $env.S3_BUCKET, region: us-east-1 }

forms:
  - id: 1
    name: apply
    title: Job Application
    path: /apply
    submitTo: { table: applications }
    fields:
      - { kind: standalone, name: full_name, inputType: single-line-text, required: true }
      - kind: standalone
        name: resume
        inputType: attachment
        label: Resume
        required: true
        accept: 'application/pdf,.doc,.docx'
        maxFileSize: 10485760 # 10 MB
        dropZone: true
```

## Configuration du champ de pièce jointe

Le comportement de pièce jointe se configure de la même manière sur les deux types de champs : un champ `kind: standalone` avec `inputType: attachment`, ou un champ `kind: table-field` dont la colonne sous-jacente est `single-attachment` / `multiple-attachments`. Les propriétés de téléversement sont partagées.

| Propriété     | Description                                                                                                                                           |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `accept`      | Types MIME ou extensions séparés par des virgules restreignant la boîte de dialogue de fichiers (par ex. `image/*`, `application/pdf`, `.doc,.docx`). |
| `maxFileSize` | Taille maximale en octets par fichier. Les fichiers plus volumineux sont rejetés avec une erreur en ligne avant le début du téléversement.            |
| `maxFiles`    | Nombre maximal de fichiers (champs multi-fichiers uniquement). En sélectionner davantage affiche une erreur en ligne.                                 |
| `dropZone`    | Affiche une zone de glisser-déposer à côté du sélecteur, acceptant les mêmes fichiers.                                                                |

:::callout
**Simple vs multiple.** Une pièce jointe simple soumet un objet `FileMetadata` (ou `null` lorsqu'elle est vide) ; une pièce jointe multiple soumet un tableau `FileMetadata[]` (ou `[]`). Pour les champs liés à une table, la multiplicité est déduite du type de colonne (`single-attachment` vs `multiple-attachments`) ; pour les champs autonomes, elle suit l'interface de téléversement présentée par `inputType: attachment` et `maxFiles`.
:::

## Liaison au bucket

La destination de stockage provient de `app.buckets[]`. Un formulaire hérite d'un **bucket par défaut** : le bucket dont l'indicateur `default: true` est défini, ou le seul bucket lorsqu'un seul est défini. Les fichiers y sont téléversés à la soumission, et la charge utile du formulaire porte les métadonnées canoniques de chaque fichier. Les surcharges de bucket par champ sont réservées à une version ultérieure.

```yaml
buckets:
  - name: documents
    default: true
    backend: local
    config: { path: ./storage/documents }

forms:
  - id: 2
    name: invoice-upload
    title: Upload Invoice
    submitTo: { automation: process-invoice }
    fields:
      - { kind: standalone, name: vendor, inputType: single-line-text, required: true }
      - kind: standalone
        name: document
        inputType: attachment
        accept: 'application/pdf,image/*'
        maxFileSize: 20971520 # 20 MB
        dropZone: true
```

## Expérience de téléversement

Le champ de pièce jointe affiche une expérience de téléversement complète :

| Comportement                | Description                                                                                                                                              |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Filtre de type              | `accept` restreint à la fois la boîte de dialogue du navigateur et le glisser-déposer ; les fichiers non conformes affichent une erreur en ligne.        |
| Validation de taille        | `maxFileSize` rejette les fichiers trop volumineux avant le début du téléversement.                                                                      |
| Indicateur de progression   | Une barre de progression ou un indicateur de chargement est affiché pendant le téléversement de chaque fichier.                                          |
| Aperçu                      | Les fichiers image affichent une vignette après le téléversement ; les fichiers non image affichent le nom + la taille.                                  |
| Suppression                 | Les fichiers sélectionnés peuvent être supprimés avant la soumission (accessible au clavier) ; en supprimer un parmi plusieurs n'affecte pas les autres. |
| Application de l'obligation | Un champ de pièce jointe `required` sans fichier bloque la soumission avec une erreur en ligne.                                                          |

## Forme des métadonnées de fichier

Lorsque le formulaire est soumis, chaque valeur de pièce jointe est normalisée en un objet de métadonnées canonique — la même forme consommée par `submitTo.table`, les déclencheurs `submitTo.automation`, et la charge utile `data` du registre `form_submissions`.

```typescript
type FileMetadata = {
  url: string // canonical URL into the bucket (signed when the bucket is private)
  name: string // original filename
  size: number // bytes
  mimeType: string // detected MIME type
}
```

Un champ simple soumet `FileMetadata | null` ; un champ multiple soumet `FileMetadata[]`. Acheminer le téléversement vers une automatisation rend les mêmes métadonnées disponibles dans la charge utile du déclencheur — par exemple pour exécuter une extraction par IA sur `{{trigger.data.document.url}}`.

## Pages associées

- [Champs de formulaire](/fr/docs/form-fields) — les types de champs que les téléversements de pièces jointes étendent.
- [Présentation des formulaires](/fr/docs/forms-overview) — les cibles `submitTo` qui reçoivent les métadonnées de fichier.
- [Soumissions](/fr/docs/form-submissions) — métadonnées de fichier stockées dans la charge utile `data` du registre.
- [Buckets](/fr/docs/buckets-overview) — configurer les backends de stockage S3, local et base de données.
