File Uploads
Handle file uploads with Supabase Storage.
Note: This is mock/placeholder content for demonstration purposes.
Enable users to upload and manage files using Supabase Storage.
Setup
Create Storage Bucket
-- Create a public bucket for avatars
INSERT INTO storage.buckets (id, name, public)
VALUES ('avatars', 'avatars', true);
-- Create a private bucket for documents
INSERT INTO storage.buckets (id, name, public)
VALUES ('documents', 'documents', false);
Set Storage Policies
-- Allow users to upload their own avatars CREATE POLICY "Users can upload their own avatar" ON storage.objects FOR INSERT WITH CHECK ( bucket_id = 'avatars' AND auth.uid()::text = (storage.foldername(name))[1] ); -- Allow users to view their own avatars CREATE POLICY "Users can view their own avatar" ON storage.objects FOR SELECT USING ( bucket_id = 'avatars' AND auth.uid()::text = (storage.foldername(name))[1] ); -- Allow users to delete their own avatars CREATE POLICY "Users can delete their own avatar" ON storage.objects FOR DELETE USING ( bucket_id = 'avatars' AND auth.uid()::text = (storage.foldername(name))[1] );
Upload Component
Basic File Upload
'use client';
import { useState } from 'react';
import { uploadFileAction } from '../_lib/actions';
export function FileUpload() {
const [uploading, setUploading] = useState(false);
const [file, setFile] = useState<File | null>(null);
const handleUpload = async () => {
if (!file) return;
setUploading(true);
const formData = new FormData();
formData.append('file', file);
const result = await uploadFileAction(formData);
if (result.success) {
toast.success('File uploaded successfully');
}
setUploading(false);
};
return (
<div>
<input
type="file"
onChange={(e) => setFile(e.files?.[0] || null)}
accept="image/*"
/>
<button
onClick={handleUpload}
disabled={!file || uploading}
>
{uploading ? 'Uploading...' : 'Upload'}
</button>
</div>
);
}
Server Action
'use server';
import { enhanceAction } from '@kit/next/actions';
import { getSupabaseServerClient } from '@kit/supabase/server-client';
export const uploadFileAction = enhanceAction(
async (formData: FormData, user) => {
const file = formData.get('file') as File;
if (!file) {
throw new Error('No file provided');
}
const client = getSupabaseServerClient();
const fileExt = file.name.split('.').pop();
const fileName = `${user.id}/${Date.now()}.${fileExt}`;
const { data, error } = await client.storage
.from('avatars')
.upload(fileName, file, {
cacheControl: '3600',
upsert: false,
});
if (error) throw error;
// Get public URL
const { data: { publicUrl } } = client.storage
.from('avatars')
.getPublicUrl(fileName);
return {
success: true,
url: publicUrl,
path: data.path,
};
},
{ auth: true }
);