P PasteCode
Prompt

Invite pour ajouter un téléchargement de fichier Cloudflare R2

Invite IA prête à copier-coller pour ajouter des URL de téléchargement présignées Cloudflare R2 à un projet Next.js App Router avec validation côté serveur.

CursorClaude CodeCodexWindsurf Next.jsCloudflareTypeScript
.md .json Difficulté: Moyen Mis à jour 8 juin 2026

Donnez cette invite à votre agent pour implémenter des téléchargements directs vers R2 via des URL présignées — en gardant les secrets côté serveur et en évitant l’erreur courante de router les octets du fichier via votre serveur Next.js.

Invite principale

Main Prompt
You are working in a Next.js App Router project using TypeScript.
Task: add Cloudflare R2 file upload via presigned PUT URLs.
Requirements:
- Install `@aws-sdk/client-s3` and `@aws-sdk/s3-request-presigner` (R2 is S3-compatible).
- Create a Server Action in `src/lib/actions/get-upload-url.ts` that:
- Accepts `{ filename: string; contentType: string; sizeBytes: number }`.
- Validates: `sizeBytes` must be <= 10_485_760 (10 MB); `contentType` must start with `image/`.
- Uses `PutObjectCommand` + `getSignedUrl` to generate a 60-second presigned URL.
- Returns `{ uploadUrl: string; publicUrl: string; key: string }`.
- Store credentials in `.env`: `R2_ACCOUNT_ID`, `R2_ACCESS_KEY_ID`, `R2_SECRET_ACCESS_KEY`,
`R2_BUCKET_NAME`, `R2_PUBLIC_URL`.
- Create a client component `src/components/FileUploader.tsx` that:
- Renders a file `<input accept="image/*" />`.
- On change: calls the Server Action to get the presigned URL, then does a `fetch` PUT directly
to R2, then shows the `publicUrl` as a preview.
- Shows upload progress via `XMLHttpRequest` `progress` events (not fetch, which lacks progress).
- Do not add any other dependencies. Do not modify `next.config.ts` unless required for image domains.
Stop and list all planned file changes before writing any code.

Notes d’implémentation

  • R2 utilise le SDK S3 avec endpoint: https://<accountId>.r2.cloudflarestorage.com et region: 'auto'. Oublier region: 'auto' provoque une erreur de signature.
  • Les URL présignées sont générées côté serveur ; le client ne voit jamais R2_SECRET_ACCESS_KEY.
  • Pour l’accès public au bucket, activez le bouton « Public access » du bucket R2 dans le tableau de bord Cloudflare et fournissez l’URL r2.dev résultante comme R2_PUBLIC_URL.

Modifications de fichiers attendues

src/lib/actions/get-upload-url.ts (new)
src/lib/r2.ts (new — S3Client singleton)
src/components/FileUploader.tsx (new — Client Component)
.env.example (edited)
package.json (edited)
next.config.ts (edited — add r2.dev to images.remotePatterns)

Critères d’acceptation

  • Un fichier sélectionné dans FileUploader déclenche une requête d’URL présignée, puis télécharge directement vers R2.
  • Les fichiers de plus de 10 Mo sont rejetés avant toute requête réseau.
  • Les types MIME non image sont rejetés côté serveur et renvoient une erreur équivalente à 400.
  • L’aperçu de l’URL publique affiche l’image téléchargée une fois le téléchargement terminé.

Commandes de test

Terminal window
bun run typecheck
bun run dev
# upload a PNG < 10 MB via the component and confirm it appears in R2 bucket
# attempt a 15 MB file and confirm rejection
# attempt a .pdf and confirm rejection

Erreurs courantes de l’IA

  • Définir region: 'us-east-1' au lieu de 'auto', provoquant des erreurs SignatureDoesNotMatch.
  • Router les octets du fichier via l’Action Serveur Next.js au lieu de les envoyer directement à R2.
  • Oublier d’appeler 'use server' en haut du fichier d’actions.
  • Utiliser fetch pour le téléchargement et perdre les événements de progression.

Invite de correction

Fix Prompt
The upload fails with `SignatureDoesNotMatch` or the file routes through the server.
Fix in order:
1. In `src/lib/r2.ts`, set `region: 'auto'` and `endpoint: https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com`.
2. In `FileUploader.tsx`, use `XMLHttpRequest` with a `progress` event to PUT directly to the
presigned URL — not fetch, and not a Server Action for the actual upload bytes.
Show corrected diff only.