Storage Uploads
Learn how to upload files to Supabase Storage.
Supabase Storage provides two methods for uploading files:
- Standard Uploads
- Resumable Uploads
Standard Upload#
The standard file upload method is ideal for small files that are not larger than 6MB.
It uses the traditional multipart/form-data
format and is simple to implement using the supabase-js SDK. Here's an example of how to upload a file using the standard upload method:
note
Though you can upload up to 5GB files using the standard upload method, we recommend use TUS Resumable Upload for uploading files greater than 6MB in size for better reliability.
_14import { createClient } from '@supabase/supabase-js'_14_14// Create Supabase client_14const supabase = createClient('your_project_url', 'your_supabase_api_key')_14_14// Upload file using standard upload_14async function uploadFile(file) {_14 const { data, error } = await supabase.storage.from('bucket_name').upload('file_path', file)_14 if (error) {_14 // Handle error_14 } else {_14 // Handle success_14 }_14}
Resumable Upload#
note
Resumable upload is in Beta. We are rolling this feature gradually, please contact us if you want to be prioritized.
The Resumable upload method is recommended for uploading large files that may exceed 6MB in size or for scenarios where network stability is a concern or if you simply want to have a progress bar for your uploads.
Supabase Storage implements the TUS protocol to enable resumable uploads. TUS stands for The Upload Server and is an open protocol for supporting resumable uploads. The protocol allows the upload process to be resumed from where it left off in case of interruptions. This method can be implemented using the tus-js-client library, or other client-side libraries like Uppy-js that support the TUS protocol.
Here's an example of how to upload a file using tus-js-client
:
_51const tus = require('tus-js-client')_51_51const projectId = ''_51_51async function uploadFile(bucketName, fileName, file) {_51 const { data: session } = await supabase.auth.session()_51_51 return new Promise((resolve, reject) => {_51 var upload = new tus.Upload(file, {_51 endpoint: `https://${projectId}.supabase.co/storage/v1/upload/resumable`,_51 retryDelays: [0, 3000, 5000, 10000, 20000],_51 headers: {_51 authorization: `Bearer ${session.access_token}`,_51 'x-upsert': 'true', // optionally set upsert to true to overwrite existing files_51 },_51 uploadDataDuringCreation: true,_51 removeFingerprintOnSuccess: true, // Important if you want to allow re-uploading the same file https://github.com/tus/tus-js-client/blob/main/docs/api.md#removefingerprintonsuccess_51 metadata: {_51 bucketName: bucketName,_51 objectName: fileName,_51 contentType: 'image/png',_51 cacheControl: 3600,_51 },_51 chunkSize: 6 * 1024 * 1024, // NOTE: it must be set to 6MB (for now) do not change it_51 onError: function (error) {_51 console.log('Failed because: ' + error)_51 reject(error)_51 },_51 onProgress: function (bytesUploaded, bytesTotal) {_51 var percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2)_51 console.log(bytesUploaded, bytesTotal, percentage + '%')_51 },_51 onSuccess: function () {_51 // console.log(upload)_51 console.log('Download %s from %s', upload.file.name, upload.url)_51 resolve()_51 },_51 })_51_51 // Check if there are any previous uploads to continue._51 return upload.findPreviousUploads().then(function (previousUploads) {_51 // Found previous uploads so we select the first one._51 if (previousUploads.length) {_51 upload.resumeFromPreviousUpload(previousUploads[0])_51 }_51_51 // Start the upload_51 upload.start()_51 })_51 })_51}
Upload URL#
When uploading using the resumable upload endpoint, the TUS server creates a unique URL for each upload, even for multiple uploads to the same path. All chunks will be uploaded to this URL using the PATCH
method.
This URL will be valid for up to 24 hours. If the upload is not completed within 24 hours, the URL will expire and you'll need to start the upload again. The TUS client library will automatically create a new URL if the previous one expires.
Concurrency#
When two or more clients try to upload to the same Upload URL only one of them will succeed. The other clients will receive a 409 Conflict
error. Only 1 client can upload to the same Upload URL at a time which prevents data corruption.
note
We do not yet support checksum validation for the uploaded chunks. This means if a client changes the file mid way through the upload, the final upload will be an amalgamation of both the files. This has to be done intentionally by the client and is unlikely to happen in normal circumstances.
When two or more clients upload a file to the same path using different upload URLs, the first client to complete the upload will succeed and the other clients will receive a 409 Conflict
error.
If you provide the x-upsert
header the last client to complete the upload will succeed instead.
UppyJS Example#
You can check a full example using UppyJS Here
Framework integration for UppyJS:
Overwriting Files#
When uploading a file to a path that already exists, the default behavior is to return a 409 Conflict
error.
If you want to overwrite a file on a specific path you can set the x-upsert
header to true
.
We do advise against overwriting files when possible, as the CDN will take sometime to propagate the changes to all the edge nodes leading to stale content. Uploading a file to a new path is the recommended way to avoid propagation delays and stale content.
If you want to know more about our CDN, check the CDN guide.
Access Control with RLS Policies#
Both the standard file upload and TUS resumable file upload methods in Supabase Storage support Row-Level Security (RLS) policies. RLS allows you to define fine-grained access control rules to restrict access to files based on user roles, permissions, or other criteria. This ensures that your files are secure and accessible only to authorized users.
For more information on RLS policies, see the Storage Access Control guide.
Conclusion#
Supabase Storage provides multiple options for uploading files, including standard file upload and TUS resumable file upload, both of which use RLS policies for access control. Additionally, there are client-side libraries like Uppy-js that make it easy to implement TUS uploads in your application. Choose the upload method that best fits your needs based on file size, network stability, and other requirements.