Next.js / Storage

    File Uploads i Media Storage

    UploadThing dla Next.js, Cloudinary transforms, AWS S3 presigned URLs, Mux video streaming i next/image optymalizacja.

    UploadThing
    Next.js native
    Cloudinary
    Media transforms
    AWS S3
    Enterprise storage
    Mux
    Video streaming

    6 rozwiązań file upload — porównanie

    UploadThing, Cloudinary, S3, R2, Mux i Multer — typ, setup, storage i idealny case użycia.

    Rozwiązanie Typ Setup Storage Kiedy
    UploadThing Managed service Minimal (Next.js native) UploadThing S3 Next.js App Router, T3 stack
    Cloudinary Media platform SDK + account Cloudinary CDN Image/video transforms, marketing
    AWS S3 + presigned Cloud storage AWS IAM + bucket S3 + CloudFront Enterprise, max control, AWS
    Cloudflare R2 Cloud storage CF account + worker R2 + CDN free Zero egress, Cloudflare ecosystem
    Mux Video platform API + Mux Player Mux CDN Video streaming, adaptive bitrate
    Multer + local/S3 Self-managed npm install multer Local / S3 Express, full control, self-host

    Często zadawane pytania

    Co to jest UploadThing i jak wdrożyć file uploads w Next.js App Router?

    UploadThing: file upload service zaprojektowany dla Next.js (Ping Labs, 2023). TypeScript-first. Obsługuje: image, video, PDF, audio, blob. Automatyczna walidacja rozmiaru/typu. CDN delivery. Instalacja: npm install uploadthing @uploadthing/react. Konfiguracja: uploadthing/core.ts — defineFileRoute('imageUploader', {image: {maxFileSize: '4MB', maxFileCount: 1}, onUploadComplete: async ({metadata, file}) => {await db.user.update({avatar: file.url})}, onBeforeUploadComplete: async ({req}) => {const session = await getServerSession(). return {userId: session.user.id}}}). Route handler: app/api/uploadthing/route.ts — {GET, POST} = createRouteHandler({router: ourFileRouter}). Client component: useUploadThing('imageUploader', {onClientUploadComplete: (res) => {toast.success('Upload complete'). router.refresh()}}). UploadButton, UploadDropzone — gotowe UI. Lub custom: startUpload(files). FileRouter type-safety: inferEndpointInput, inferEndpointOutput. Przesyłaj metadata przez onUploadComplete. Klucz API: UPLOADTHING_SECRET, UPLOADTHING_APP_ID. Pliki przechowywane na UploadThing S3. URL do pliku: gotowy link CDN. Usuwanie: utapi.deleteFiles(fileKey). Limitowanie: maxFileSize, maxFileCount per route. Middleware: restrict per auth status. Dokumentacja: docs.uploadthing.com. T3 stack integration — wbudowane.

    Cloudinary i AWS S3 — zarządzanie mediami i storage w chmurze?

    Cloudinary: media management platform. Upload, transform, optimize, deliver. CDN wbudowany. Image transformations: resize, crop, format conversion, quality. f_auto — format auto (WebP dla Chrome, AVIF dla supported). q_auto — quality auto. w_800,h_600,c_fill — resize i crop. Cloudinary SDK: cloudinary.uploader.upload(file, {folder: 'avatars', transformation: [{width: 200, height: 200, crop: 'thumb', gravity: 'face'}]}). Result: secure_url, public_id. React: CldImage component (next-cloudinary). CldUploadWidget — drag and drop upload. Video: adaptive streaming (HLS), auto transcoding. AWS S3: scalable object storage. Direct upload pattern: Server generuje presigned URL. Client uploaduje bezpośrednio do S3 (nie przez serwer). Unika obciążenia serwera. Presigned URL: s3Client.send(new PutObjectCommand({Bucket: 'my-bucket', Key: fileKey, ContentType: file.type})). getSignedUrl(s3Client, command, {expiresIn: 300}). Client: fetch(presignedUrl, {method: 'PUT', body: file, headers: {'Content-Type': file.type}}). Security: Bucket Policy — public read dla publicznych assets. Private dla user data — presigned read URLs. CORS configuration na Bucket. AWS S3 + CloudFront CDN: dystrybucja plików globalnie. Cache headers. Cache invalidation. R2 (Cloudflare): S3-compatible storage. Brak egress fees. Zero-cost CDN. Cheaper than S3 dla read-heavy. workers.cloudflare.com/r2. Backblaze B2: najtańszy. S3-compatible. $0.006/GB storage.

    Multer i Formidable — file uploads w Node.js bez SaaS?

    Multer: middleware do multipart/form-data (file uploads) w Express. const storage = multer.diskStorage({destination: (req, file, cb) => cb(null, './uploads'), filename: (req, file, cb) => cb(null, Date.now() + extname(file.originalname))}). const upload = multer({storage, limits: {fileSize: 5 * 1024 * 1024}, fileFilter: (req, file, cb) => {if (!['image/jpeg', 'image/png'].includes(file.mimetype)) return cb(new Error('Invalid type')). cb(null, true)}}). router.post('/upload', upload.single('avatar'), (req, res) => {res.json({path: req.file.path})}). Memory storage: multer.memoryStorage() — do bufferu (dla cloud upload). req.file.buffer -> S3 upload. Formidable: alternatywa dla Multer. Wspiera Node.js 18+. Streaming. Fastify Multipart: @fastify/multipart. await request.file(). part.file -> stream. Pipe to S3. Next.js App Router uploads: Brak multer (Edge kompatybilny). FormData API. const formData = await request.formData(). const file = formData.get('file') as File. const buffer = Buffer.from(await file.arrayBuffer()). Potem: save do disk lub upload do S3/Cloudinary. Sharp: image processing w Node.js. sharp(buffer).resize(200, 200).webp().toBuffer(). Konwersja formatów. Metadata extraction. Blurhash: compact blurry placeholder. blurhash.encode(pixels, width, height). React: Blurhash component. Pokazuj placeholder podczas ładowania. File validation: magic bytes zamiast extension. fileTypeFromBuffer(buffer) — prawdziwy typ pliku. PDF: sprawdź %PDF header.

    Video uploads — Mux, Cloudinary Video i YouTube Data API?

    Mux: video infrastructure as a service. Upload -> transcode -> streaming. Mux Player: React component. Adaptive bitrate (HLS). Thumbnails automatyczne. Data: analytics per viewer. Mux Data: QoE (Quality of Experience) metrics. Instalacja: npm install @mux/mux-node @mux/mux-player-react. Upload flow: mux.Video.Uploads.create({new_asset_settings: {playback_policy: ['public']}, cors_origin: '*'}). Zwróć upload_url do klienta. Klient uploaduje bezpośrednio PUT do upload_url. Webhook: video.upload.asset_created -> asset ready. asset.id -> playback_id. Odtwarzanie: MuxPlayer playback-id={playbackId}. Thumbnail: image.mux.com/{playbackId}/thumbnail.jpg. Cloudinary Video: transformacje wideo. f_mp4, f_webm. Konwersja na GIF. Sprite thumbnails. YouTube Data API: upload do YouTube programatycznie. OAuth2 wymagane. media.insert(). Status polling. YouTube jako CDN video. Vimeo API: podobne do YouTube. Privacy controls. Password protected. Uploadcare: wszystko-w-jednym. Image, video, audio. Transformacje w URL. Widget gotowy. Self-hosted alternatywa: MinIO — S3-compatible self-host. MediaInfo: parse video metadata. ffprobe: duration, resolution, codec. ffmpeg: transcode video. Render.com lub Railway dla ffmpeg. Chunked uploads: duże pliki (1GB+). tus protocol: resumable. Upload w kawałkach. Uppy.js: client library. Obsługuje tus, S3, Cloudinary. Drag and drop UI. Thumbnails, progress.

    Image optimization w Next.js — next/image, AVIF, WebP i CDN?

    next/image: automatyczna optymalizacja. Lazy loading. Placeholder (blur). Size optimization. Modern formats (WebP, AVIF). Image component: Image src='/photo.jpg' alt='Opis' width={800} height={600}. fill — zajmuje rodzica (potrzebuje relative parent). priority — preload dla LCP image. placeholder='blur' blurDataURL={base64}. sizes='(max-width: 768px) 100vw, 50vw'. Formaty: automatycznie serwuje WebP lub AVIF (gdy supported). AVIF: 50% mniejszy od JPEG. WebP: 30% mniejszy od JPEG. Optymalizacja przy requestcie (on-demand). Cache na dysku serwera. External images: remotePatterns config w next.config.js. {protocol: 'https', hostname: 'images.example.com'}. next/image + Cloudinary: CldImage (next-cloudinary) — use Cloudinary CDN. Placeholder loading. Transformacje URL. Generowanie blurDataURL: plaiceholder — generuje base64 blur. const {base64} = await getPlaiceholder(imageUrl). LQIP (Low Quality Image Placeholder). Image CDN comparison: Vercel Image Optimization — za darmo na Vercel ($0.005/1K po limit). Cloudinary — transforms + analytics. Imgix — custom domains, transforms. Bunny.net — CDN + image optimizer. Sharp optymalizacja server-side: sharp(buffer).webp({quality: 80}).toBuffer(). Zaawansowane: .resize({width: 800, fit: 'inside', withoutEnlargement: true}). srcset i sizes: Next.js generuje automatycznie srcset. Przeglądarka wybiera najlepszy rozmiar. Lighthouse Image Audit — sprawdź 'properly sized images'. Core Web Vitals: LCP image = priority prop. Lazy load fold-below images.

    Czytaj dalej

    Powiązane artykuły

    Kontakt

    Skontaktuj się z nami

    Porozmawiajmy o Twoim projekcie. Bezpłatna wycena w ciągu 24 godzin.

    Wyślij zapytanie

    Bezpłatna wycena w 24h
    Bez zobowiązań
    Indywidualne podejście
    Ekspresowa realizacja

    Telefon

    +48 790 814 814

    Pon-Pt: 9:00 - 18:00

    Email

    adam@fotz.pl

    Odpowiadamy w ciągu 24h

    Adres

    Plac Wolności 16

    61-739 Poznań

    Godziny pracy

    Pon - Pt9:00 - 18:00
    Sob - NdzZamknięte

    Wolisz porozmawiać?

    Zadzwoń teraz i porozmawiaj z naszym specjalistą o Twoim projekcie.

    Zadzwoń teraz