Created
May 5, 2024 01:32
-
-
Save officialrobert/fe2e4a96c16463b8ed2304e9b3f54c07 to your computer and use it in GitHub Desktop.
How to do resumable upload using supabase storage
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Upload } from 'tus-js-client'; | |
import { isEmpty, head } from 'lodash'; | |
function uploadFile( | |
file: File, | |
accessToken: string, | |
bucketName: string, | |
fileName: string, | |
contentType: string, | |
folder?: string | |
): Promise<{ url: string; name: string } | null> { | |
return new Promise((resolve, reject) => { | |
const supabaseProjectId = 'your-project-id'; | |
const publicAuthFilesFolder = 'public-folder'; | |
const filePath = `${ | |
!isEmpty(folder) ? folder : publicAuthFilesFolder | |
}/${fileName}`; | |
const upload = new Upload(file, { | |
endpoint: `https://${supabaseProjectId}.supabase.co/storage/v1/upload/resumable`, | |
retryDelays: [0, 3000, 5000, 10000, 20000], | |
headers: { | |
apikey: supabasePublicKey, // API key from supabase settings | |
authorization: `Bearer ${accessToken}`, // Auth required because I have RLS enabled for this folder | |
'x-upsert': 'true', // optionally set upsert to true to overwrite existing files | |
}, | |
uploadDataDuringCreation: true, | |
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 | |
metadata: { | |
...(!isEmpty(contentType) && { contentType }), | |
bucketName: bucketName, | |
objectName: filePath, | |
cacheControl: '3600', | |
}, | |
chunkSize: 6 * 1024 * 1024, // NOTE: it must be set to 6MB (for now) do not change it | |
onError: function (error) { | |
console.log('Failed because: ' + error); | |
reject(error); | |
}, | |
onProgress: function (bytesUploaded, bytesTotal) { | |
const percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2); | |
console.log(bytesUploaded, bytesTotal, percentage + '%'); | |
}, | |
onSuccess: function () { | |
// @ts-ignore | |
const fileName = upload.file?.name || ''; | |
const url = upload?.url; | |
if (url) { | |
const { data: urlData } = supabaseClient.storage | |
.from(bucketName) | |
.getPublicUrl(`${filePath}`); | |
const publicUrl = urlData?.publicUrl || ''; | |
console.log('onSuccess() publicUrl:', publicUrl); | |
resolve({ | |
url: publicUrl, | |
name: fileName, | |
}); | |
} | |
resolve(null); | |
}, | |
}); | |
// Check if there are any previous uploads to continue. | |
return upload.findPreviousUploads().then(function (previousUploads) { | |
// Found previous uploads so we select the first one. | |
if (previousUploads.length) { | |
upload.resumeFromPreviousUpload(previousUploads[0]); | |
} | |
upload.start(); | |
}); | |
}); | |
} | |
// HOW TO CALL | |
// Callback handler for <input type='file'/> | |
const handleFileUpload = async (evt) => { | |
const file = head(evt?.target?.files); | |
if (file) { | |
// await uploadFile(file, ...continue with other params) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment