Indicación para agregar carga de archivos a Cloudflare R2
Indicación de IA para copiar y pegar y agregar URLs de carga presignadas de Cloudflare R2 a un proyecto de Next.js App Router con validación del lado del servidor.
CursorClaude CodeCodexWindsurf Next.jsCloudflareTypeScript
Proporciona esta indicación a tu agente para implementar cargas de archivos directas a R2 utilizando URLs presignadas — manteniendo los secretos en el lado del servidor y evitando el error común de enrutar los bytes del archivo a través de tu servidor de Next.js.
Indicación principal
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.Notas de implementación
- R2 usa el SDK de S3 con
endpoint: https://<accountId>.r2.cloudflarestorage.comyregion: 'auto'. Olvidarregion: 'auto'provoca un error de firma. - Las URLs presignadas se generan del lado del servidor; el cliente nunca ve
R2_SECRET_ACCESS_KEY. - Para el acceso público al bucket, activa la opción “Acceso público” del bucket R2 en el panel de Cloudflare
y proporciona la URL
r2.devresultante comoR2_PUBLIC_URL.
Cambios esperados en archivos
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)Criterios de aceptación
- Un archivo seleccionado en
FileUploaderactiva una solicitud de URL presignada, luego sube directamente a R2. - Los archivos de más de 10 MB se rechazan antes de cualquier solicitud de red.
- Los tipos MIME que no sean imágenes se rechazan del lado del servidor y devuelven un error equivalente a 400.
- La vista previa de la URL pública renderiza la imagen subida después de que la carga se completa.
Comandos de prueba
bun run typecheckbun 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 rejectionErrores comunes de IA
- Establecer
region: 'us-east-1'en lugar de'auto', causando errores deSignatureDoesNotMatch. - Enrutar los bytes del archivo a través de la Server Action de Next.js en lugar de obtenerlos directamente a R2.
- Olvidar llamar a
'use server'al principio del archivo de acciones. - Usar
fetchpara la carga y perder eventos de progreso.
Indicación de corrección
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.