File Upload Reference
Use useFileUpload to upload user-selected files to blob storage and receive a public URL that can be displayed, persisted, passed to AI hooks, or downloaded later.
useFileUpload
Import the hook from the file upload module:
import { useFileUpload } from "@/hooks/use-file-upload";
import { usePersistentItem } from "@/hooks/use-persistent-item";
export default function App() {
const [uploadedImageUrl, setUploadedImageUrl] = usePersistentItem<
string | null
>("uploadedImageUrl", null);
const [selectedFile, setSelectedFile] = React.useState<File | null>(null);
const { uploadFile, isLoading, error } = useFileUpload();
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setSelectedFile(event.target.files?.[0] ?? null);
};
const handleUpload = async () => {
if (!selectedFile) return;
const result = await uploadFile(selectedFile);
if (result) {
setUploadedImageUrl(result.url);
setSelectedFile(null);
}
};
return (
<div>
<div className="flex gap-2">
<input
type="file"
accept="image/png, image/jpeg, image/webp"
onChange={handleFileChange}
/>
<button onClick={handleUpload} disabled={!selectedFile || isLoading}>
{isLoading ? <span className="inline-block mr-2 animate-spin rounded-full border-2 border-current border-t-transparent" /> : null}
Upload
</button>
</div>
{error && <p className="text-destructive">{error.message}</p>}
{uploadedImageUrl && (
<img src={uploadedImageUrl} alt="Uploaded" className="w-full rounded-lg" />
)}
</div>
);
}
Error Handling
Uploads return undefined on failure:
const { uploadFile, error, isLoading } = useFileUpload();
const handleUpload = async (file: File) => {
const result = await uploadFile(file);
if (!result) {
console.error("Upload failed:", error?.message);
return;
}
console.log("Uploaded to:", result.url);
};
Best Practices
- Upload one file at a time per hook instance. Use multiple hook instances for concurrent uploads.
- Persist
result.urlwithusePersistentItemwhen the file should survive reloads. - Stream files directly to storage instead of reading large files into memory.
- Use the returned
contentTypewhen displaying or categorizing uploaded files. - Pass uploaded URLs to AI hooks as
{ url }attachments when you need AI processing. - Keep local
Filestate separate from persisted URLs so users can clear or retry selections cleanly.