Last active
August 1, 2024 00:08
-
-
Save gregfenton/f82a953feef12c17fd82f548e60a4c53 to your computer and use it in GitHub Desktop.
JavaScript to upload a file/URL from React-Native (Expo) to Firebase Storage -- updated to the Firebase "modular API" syntax
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
// | |
// `npx expo install cuid firebase` | |
// | |
import { myStorage } from './firebase.js'; | |
import { ref, getDownloadURL, uploadBytesResumable } from 'firebase/storage'; | |
import cuid from 'cuid'; | |
/** | |
* Uploads data from given `uri` to Firebase Storage and returns | |
* | |
* @param {URI} imagePickerResult the URI for the data to be uploaded | |
* @param {string} storageFolderName the name of the storage folder | |
* @param {function} progressCallback called by Firebase Storage as the upload progresses | |
* @param {function} downloadUrlCallback called by Firebase Storage and passes the downloadURL to it | |
*/ | |
export const fbUriToFirebaseStorage = async ( | |
imagePickerResult, | |
storageFolderName, | |
progressCallback = null, | |
downloadUrlCallback = null | |
) => { | |
console.log('imagePickerResult is:', imagePickerResult); | |
try { | |
const ext = imagePickerResult.uri?.split('.').pop() || 'png'; | |
const filename = cuid() + '.' + ext; | |
// From: https://github.com/expo/examples/blob/master/with-firebase-storage-upload/App.js | |
const blob = await new Promise((resolve, reject) => { | |
const xhr = new XMLHttpRequest(); | |
xhr.onload = function () { | |
resolve(xhr.response); | |
}; | |
xhr.onerror = function (e) { | |
console.log(e); | |
reject(new TypeError('Network request failed')); | |
}; | |
xhr.responseType = 'blob'; | |
xhr.open('GET', imagePickerResult.uri, true); | |
xhr.send(null); | |
}); | |
const uploadTask = fbUploadToFirebaseStorage( | |
blob, | |
filename, | |
storageFolderName | |
); | |
uploadTask.on( | |
'state_changed', | |
(snapshot) => { | |
progressCallback && | |
progressCallback(snapshot.bytesTransferred / snapshot.totalBytes); | |
}, | |
(error) => { | |
console.error('ERROR uploading image:', error.message); | |
throw error; | |
}, | |
async () => { | |
try { | |
let downloadUrl = await getDownloadURL(uploadTask.snapshot.ref); | |
downloadUrlCallback && downloadUrlCallback(downloadUrl); | |
} catch (error) { | |
console.error(`ERROR updating user profile pic: ${error.message}`); | |
} finally { | |
blob.close(); // release the blob! | |
} | |
} | |
); | |
} catch (ex) { | |
console.error('Exception from fbUriToFirebaseStorage(): ', ex.message); | |
} | |
}; | |
/** | |
* | |
* @param {Blob} blob - the data of the file being uploaded | |
* @param {string} filename - name to use for file storage | |
* @param {string} storageFolderName - name of folder in Firebase Storage; if null, default's to user's "misc" folder | |
* | |
* @returns an `UploadTask` from Firebase Storage API | |
* @see https://firebase.google.com/docs/reference/js/firebase.storage.Reference#put | |
*/ | |
export const fbUploadToFirebaseStorage = ( | |
blob, | |
filename, | |
storageFolderName | |
) => { | |
if (!storageFolderName) { | |
throw new Error('You must provide a value for `storageFolderName`'); | |
} | |
let theRef = ref(myStorage, `${storageFolderName}/${filename}`); | |
return uploadBytesResumable(theRef, blob); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment