@upstash/blob has React hooks that upload from the browser straight to storage. This page builds a working file picker in React. The server code is Next.js App Router in TypeScript, FastAPI in Python, or net/http in Go. Other frameworks work the same way; see Other frameworks in TypeScript, Mounting it in Python and Mounting it in Go.
Setup
upstash-blob is the Python server SDK and github.com/upstash/blob-go the Go one. The browser side is @upstash/blob whichever language runs the server, so a Python or Go app installs both.
Create a bucket in the Upstash Console and put its token in your environment.
.env
- Public: every object has a public URL. For avatars, product images, anything a page links to directly.
- Private: no public URL. Every read goes through a time-limited signed URL. For user documents, invoices, anything that must not be guessable.
Upload from your server
put. The returned record’s URL is the public object URL, not set on a private bucket. See Writing, and the TypeScript SDK, Python SDK or Go SDK for setup details.
Upload from the browser
Files a user picks go straight from the browser to storage. Your server only authorizes the upload and records the result, so the bytes never pass through it.1
Write the upload handler
2
Mount it as a route
POST runs the upload and GET serves the route’s constraints. The hooks look at /api/upload by default, so nothing else has to name a URL.3
Bind the hooks to the handler
lib/upload-hooks.ts
uploadHooks<typeof uploads>() reads the handler’s type, so route names and completion data are checked at compile time. The import type is erased at build time and never pulls server code into the browser bundle.A Python or Go handler has no type to bind to. Call uploadHooks() with no type parameter and pass the URL, useUpload("/api/upload"), in the next step. FastAPI + React has the whole app, including the dev proxy that puts /api on the page’s origin.4
Upload a file
app/page.tsx
- Multipart for large files. Past 16 MB the SDK switches to parts, with pause, resume and per-part retry. See Large files.
- Retries. Failed parts back off and retry, and an expired signature is refreshed mid-upload.
- A picker that matches the server.
acceptcomes from the route’s ownGET, so an oversized file is refused before any request goes out. See Constraints. - Progress.
percent,statusandpendingread the same for one PUT or 200 parts. - Types end to end. With a TypeScript handler, whatever
onUploadCompletereturns isupload.blob.dataon the client, typed.
Next steps
Upload handler
Auth, routes, and the completion callback in full.
Upload client
useUpload, the record it renders, and the non-React client.Writing
put, metadata, conditional writes and multipart from the server.Recipes
Avatars, attachments and private documents, wired end to end.