file-upload
Installation
SKILL.md
Wire file uploads using presigned URLs — client uploads directly to storage, your server never touches the bytes. Reads the project first, picks the right storage provider.
Four things that silently break file uploads
- CORS not configured on the bucket. The browser makes a direct PUT to R2/S3. Without CORS rules allowing your origin, every upload fails with a CORS error. Vercel Blob handles this automatically — R2 and S3 don't.
- MIME type validation on the client only. The
acceptattribute on<input>is cosmetic — users can bypass it. Always validate the MIME type server-side when generating the presigned URL, not just on the client. - No file size check before generating the presigned URL. If you generate a presigned URL and then the user uploads a 500MB file, it succeeds. Set a
ContentLengthRangecondition on S3/R2 presigned URLs, or checkContent-Lengthon the initial request. - Storing the presigned URL path as the permanent file URL. Presigned URLs expire. Store the permanent public URL (or your own proxy route), not the presigned URL.
Phase 1: Detect the Project
cat package.json | grep -E "@vercel/blob|@aws-sdk|@cloudflare"
@vercel/blob→ Vercel Blob (simplest for Vercel-hosted apps)@aws-sdk/client-s3→ AWS S3@cloudflare/workers-typesor Wrangler → Cloudflare R2- None → ask the user (default: Vercel Blob if on Vercel)