Home

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.


_14
import { createClient } from '@supabase/supabase-js'
_14
_14
// Create Supabase client
_14
const supabase = createClient('your_project_url', 'your_supabase_api_key')
_14
_14
// Upload file using standard upload
_14
async 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:


_51
const tus = require('tus-js-client')
_51
_51
const projectId = ''
_51
_51
async 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.