new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Supabase · Storage · all subjects

storage/uploads

91 notes in this subject, read out of this brain and free to use. This is page 2 of 2.

Python contentType upload example

response = supabase.storage.from_('bucket_name').upload('file_path', file, { 'content-type': 'image/jpeg', })

Content type default behavior

By default, Storage will assume the content type of an asset from the file extension.

Standard upload method file size limit

The standard file upload method is ideal for small files that are not larger than 6MB. Though you can upload up to 5GB files using the standard upload method, Supabase recommends using TUS Resumable Upload for uploading files greater than 6MB in size for better reliability.

Standard upload uses multipart/form-data format

File uploads with the supabase-js SDK use the traditional multipart/form-data format.

JavaScript standard upload example

import { createClient } from '@supabase/supabase-js' const supabase = createClient('your_project_url', 'your_supabase_api_key') async function uploadFile(file) { const { data, error } = await supabase.storage.from('bucket_name').upload('file_path', file) if (error) { // Handle error } else { // Handle success } }

Default behavior when uploading to existing path

When uploading a file to a path that already exists, the default behavior is to return a 400 Asset Already Exists error.

Upsert option to overwrite files

To overwrite a file on a specific path, set the upsert option to true or use the x-upsert header.

JavaScript upsert upload example

const supabase = createClient('your_project_url', 'your_supabase_api_key') const file = new Blob() await supabase.storage.from('bucket_name').upload('file_path', file, { upsert: true, })

cURL upsert upload example

curl -X POST "https://{your_project_ref}.supabase.co/storage/v1/object/{bucket_name}/{file_path}" \ -H "apikey: {your_anon_key}" \ -H "Authorization: Bearer {your_jwt_token}" \ -H "x-upsert: true" \ --data-binary "@/local/path/to/your/file.ext"

ContentType option for uploads

To specify the content type for an asset, pass the contentType option during upload.

JavaScript contentType upload example

const supabase = createClient('your_project_url', 'your_supabase_api_key') const file = new Blob() await supabase.storage.from('bucket_name').upload('file_path', file, { contentType: 'image/jpeg', })

cURL Content-Type header example

curl -X POST "https://{your_project_ref}.supabase.co/storage/v1/object/{bucket_name}/{file_path}" \ -H "apikey: {your_anon_key}" \ -H "Authorization: Bearer {your_jwt_token}" \ -H "Content-Type: {Content-Type}" \ --data-binary "@/local/path/to/your/file.ext"

Batch size limit for vector operations

Maximum of 1000 vectors per single insert or update request.

Resumable upload recommendations

Resumable uploads are recommended when uploading large files that may exceed 6MB in size, network stability is a concern, or you want progress events for uploads.

TUS protocol implementation in Supabase Storage

Supabase Storage implements the TUS protocol (The Upload Server) to enable resumable uploads. The protocol allows the upload process to be resumed from where it left off in case of interruptions. This can be implemented using the tus-js-client library or other libraries like Uppy that support the TUS protocol.

Direct storage hostname for large file uploads

For optimal performance when uploading large files, use the direct storage hostname instead of the standard project URL. Use https://project-id.storage.supabase.co instead of https://project-id.supabase.co. This provides several performance enhancements that greatly improve performance when uploading large files.

JavaScript resumable upload with tus-js-client

The following example shows how to upload a file using tus-js-client with Supabase Storage: ```javascript const tus = require('tus-js-client') const projectId = '' async function uploadFile(bucketName, fileName, file) { const { data: { session } } = await supabase.auth.getSession() return new Promise((resolve, reject) => { var upload = new tus.Upload(file, { // Supabase TUS endpoint (with direct storage hostname) endpoint: `https://${projectId}.storage.supabase.co/storage/v1/upload/resumable`, retryDelays: [0, 3000, 5000, 10000, 20000], headers: { authorization: `Bearer ${session.access_token}`, 'x-upsert': 'true', // optionally set upsert to true to overwrite existing files }, uploadDataDuringCreation: true, removeFingerprintOnSuccess: true, metadata: { bucketName: bucketName, objectName: fileName, contentType: 'image/png', cacheControl: '3600', metadata: JSON.stringify({ yourCustomMetadata: true, }), }, chunkSize: 6 * 1024 * 1024, onError: function (error) { console.log('Failed because: ' + error) reject(error) }, onProgress: function (bytesUploaded, bytesTotal) { var percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2) console.log(bytesUploaded, bytesTotal, percentage + '%') }, onSuccess: function () { console.log('Download %s from %s', upload.file.name, upload.url) resolve() }, }) return upload.findPreviousUploads().then(function (previousUploads) { if (previousUploads.length) { upload.resumeFromPreviousUpload(previousUploads[0]) } upload.start() }) }) } ```

Chunk size for TUS resumable uploads

The chunk size for TUS resumable uploads must be set to 6MB (6 * 1024 * 1024 bytes). Do not change this value.

React resumable upload with Uppy and TUS

The following example shows how to configure Uppy with Supabase for resumable uploads in React: ```javascript import { useEffect, useState } from "react"; import { createClient } from "@supabase/supabase-js"; import Uppy from "@uppy/core"; import Tus from "@uppy/tus"; import Dashboard from "@uppy/dashboard"; import "@uppy/core/dist/style.min.css"; import "@uppy/dashboard/dist/style.min.css"; function App() { const uppy = useUppyWithSupabase({ bucketName: "sample" }); useEffect(() => { uppy.use(Dashboard, { inline: true, target: "#drag-drop-area", showProgressDetails: true, }); }, []); return ( <div id="drag-drop-area"> </div> ); } export default App; export const useUppyWithSupabase = ({ bucketName }: { bucketName: string }) => { const [uppy] = useState(() => new Uppy()); const supabase = createClient(`https://${projectId}.supabase.co`, publishableKey); useEffect(() => { const initializeUppy = async () => { const { data: { session }, } = await supabase.auth.getSession(); uppy.use(Tus, { endpoint: `https://${projectId}.storage.supabase.co/storage/v1/upload/resumable`, retryDelays: [0, 3000, 5000, 10000, 20000], headers: { authorization: `Bearer ${session?.access_token}`, apikey: anonKey, }, uploadDataDuringCreation: true, removeFingerprintOnSuccess: true, chunkSize: 6 * 1024 * 1024, allowedMetaFields: [ "bucketName", "objectName", "contentType", "cacheControl", "metadata", ], onError: (error) => console.error("Upload error:", error), }).on("file-added", (file) => { file.meta = { ...file.meta, bucketName, objectName: file.name, contentType: file.type, metadata: JSON.stringify({ yourCustomMetadata: true, }), }; }); }; initializeUppy(); }, [uppy, bucketName]); return uppy; }; ```

Kotlin resumable upload

Kotlin supports resumable uploads natively for all targets: ```kotlin suspend fun uploadFile(file: File) { val upload: ResumableUpload = supabase.storage.from("bucket_name") .resumable.createOrContinueUpload("file_path", file) upload.stateFlow .onEach { println(it.progress) } .launchIn(yourCoroutineScope) upload.startOrResumeUploading() } suspend fun uploadData(bytes: ByteArray) { val upload: ResumableUpload = supabase.storage.from("bucket_name") .resumable.createOrContinueUpload(bytes, "source", "file_path") upload.stateFlow .onEach { println(it.progress) } .launchIn(yourCoroutineScope) upload.startOrResumeUploading() } ```

Python resumable upload with tus-py-client

The following example shows how to upload a file using tus-py-client with Supabase: ```python from io import BufferedReader from tusclient import client from supabase import create_client def upload_file( bucket_name: str, file_name: str, file: BufferedReader, access_token: str ): # create Tus client my_client = client.TusClient( f"{supabase_url}/storage/v1/upload/resumable", headers={"Authorization": f"Bearer {access_token}", "x-upsert": "true"}, ) uploader = my_client.uploader( file_stream=file, chunk_size=(6 * 1024 * 1024), metadata={ "bucketName": bucket_name, "objectName": file_name, "contentType": "image/png", "cacheControl": "3600", }, ) uploader.upload() # create client and sign in supabase = create_client(supabase_url, supabase_key) # retrieve the current user's session for authentication session = supabase.auth.get_session() # open file and send file stream to upload with open("./assets/40mb.jpg", "rb") as fs: upload_file( bucket_name="assets", file_name="large_file", file=fs, access_token=session.access_token, ) ```

C# resumable upload

C# supports resumable uploads natively via UploadOrResume method: ```c# await supabase.Storage.From("bucket_name") .UploadOrResume("local_file_path", "file_path", new FileOptions { Upsert = true }); ```

Resumable upload URL validity period

When uploading using the resumable upload endpoint, the storage server creates a unique URL for each upload. This unique upload URL will be valid for up to 24 hours. If the upload is not completed within 24 hours, the URL will expire and you need to start the upload again. TUS client libraries typically create a new URL if the previous one expires.

Resumable upload URL concurrency behavior

When two or more clients upload to the same upload URL, only one of them will succeed and 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. 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 the x-upsert header is provided, the last client to complete the upload will succeed instead.

getSession usage for resumable uploads

When using resumable uploads, getSession is appropriate to retrieve the raw access token string to forward as a credential to Supabase storage, since the code only needs the token value and validates it server-side, not making client-side auth decisions based on session data.

Presigned upload tokens for resumable uploads

Resumable uploads support using signed upload tokens to create time-limited URLs that can be shared to users. This is done by invoking the createSignedUploadUrl method on the SDK and including the returned token in the x-signature header of the resumable upload.

JavaScript presigned upload example

The following example shows how to create a signed upload URL in JavaScript: ```typescript // Create a signed upload URL const { data } = await supabase.storage.from('bucket_name').createSignedUploadUrl('file_path', { upsert: true, // Optional: allow overwriting existing files }) // Use the signed URL token in resumable upload headers // Include data.token in the x-signature header ```

Python presigned upload example

The following example shows how to create a signed upload URL in Python: ```python # Create a signed upload URL with upsert option response = supabase.storage.from_('bucket_name').create_signed_upload_url( 'file_path', options={'upsert': 'true'} # Optional: allow overwriting existing files ) # Use the signed URL token in resumable upload headers # Include response.token in the x-signature header ```

C# presigned upload example

The following example shows how to create a signed upload URL in C#: ```c# // Create a signed upload URL var signedUrl = await supabase.Storage.From("bucket_name").CreateUploadSignedUrl("file_path"); // Use the signed URL token in resumable upload headers // Include signedUrl.Token in the x-signature header ```

Overwriting files in resumable uploads

When uploading a file to a path that already exists, the default behavior is to return a 400 Asset Already Exists error. To overwrite a file on a specific path, set the x-upsert header to true.

File overwriting and CDN propagation

When overwriting files, the CDN will take some time to propagate the changes to all edge nodes, leading to stale content. Uploading a file to a new path is the recommended way to avoid propagation delays and stale content.

Give your agent this brain