Stay organized with collectionsSave and categorize content based on your preferences.
Cloud Storage for Firebaseallows you to quickly and easily upload files to aCloud Storagebucket provided
and managed by Firebase.
Upload Files
To upload a file toCloud Storage, you first create a reference to the
full path of the file, including the file name.
Kotlin
// Create a storage reference from our appvalstorageRef=storage.reference// Create a reference to "mountains.jpg"valmountainsRef=storageRef.child("mountains.jpg")// Create a reference to 'images/mountains.jpg'valmountainImagesRef=storageRef.child("images/mountains.jpg")// While the file names are the same, the references point to different filesmountainsRef.name==mountainImagesRef.name// truemountainsRef.path==mountainImagesRef.path// false
// Create a storage reference from our appStorageReferencestorageRef=storage.getReference();// Create a reference to "mountains.jpg"StorageReferencemountainsRef=storageRef.child("mountains.jpg");// Create a reference to 'images/mountains.jpg'StorageReferencemountainImagesRef=storageRef.child("images/mountains.jpg");// While the file names are the same, the references point to different filesmountainsRef.getName().equals(mountainImagesRef.getName());// truemountainsRef.getPath().equals(mountainImagesRef.getPath());// false
Once you've created an appropriate reference, you then call theputBytes(),putFile(), orputStream()method to upload the file
toCloud Storage.
You cannot upload data with a reference to the root of yourCloud Storagebucket. Your reference must point to a child URL.
Upload from data in memory
TheputBytes()method is the simplest way to upload a
file toCloud Storage.putBytes()takes abyte[]and returns anUploadTaskthat you can use to manage and monitor the status of the upload.
Kotlin
// Get the data from an ImageView as bytesimageView.isDrawingCacheEnabled=trueimageView.buildDrawingCache()valbitmap=(imageView.drawableasBitmapDrawable).bitmapvalbaos=ByteArrayOutputStream()bitmap.compress(Bitmap.CompressFormat.JPEG,100,baos)valdata=baos.toByteArray()varuploadTask=mountainsRef.putBytes(data)uploadTask.addOnFailureListener{// Handle unsuccessful uploads}.addOnSuccessListener{taskSnapshot->// taskSnapshot.metadata contains file metadata such as size, content-type, etc.// ...}
// Get the data from an ImageView as bytesimageView.setDrawingCacheEnabled(true);imageView.buildDrawingCache();Bitmapbitmap=((BitmapDrawable)imageView.getDrawable()).getBitmap();ByteArrayOutputStreambaos=newByteArrayOutputStream();bitmap.compress(Bitmap.CompressFormat.JPEG,100,baos);byte[]data=baos.toByteArray();UploadTaskuploadTask=mountainsRef.putBytes(data);uploadTask.addOnFailureListener(newOnFailureListener(){@OverridepublicvoidonFailure(@NonNullExceptionexception){// Handle unsuccessful uploads}}).addOnSuccessListener(newOnSuccessListener<UploadTask.TaskSnapshot>(){@OverridepublicvoidonSuccess(UploadTask.TaskSnapshottaskSnapshot){// taskSnapshot.getMetadata() contains file metadata such as size, content-type, etc.// ...}});
BecauseputBytes()accepts abyte[], it requires your app to hold the entire
contents of a file in memory at once. Consider usingputStream()orputFile()to use less memory.
Upload from a stream
TheputStream()method is the most versatile way to upload a
file toCloud Storage.putStream()takes anInputStreamand returns
anUploadTaskthat you can use to manage and monitor the status of the upload.
Kotlin
valstream=FileInputStream(File("path/to/images/rivers.jpg"))uploadTask=mountainsRef.putStream(stream)uploadTask.addOnFailureListener{// Handle unsuccessful uploads}.addOnSuccessListener{taskSnapshot->// taskSnapshot.metadata contains file metadata such as size, content-type, etc.// ...}
You can upload local files on the device, such as photos and videos from the
camera, with theputFile()method.putFile()takes aFileand returns anUploadTaskwhich you can use to manage and monitor the status of the upload.
Kotlin
varfile=Uri.fromFile(File("path/to/images/rivers.jpg"))valriversRef=storageRef.child("images/${file.lastPathSegment}")uploadTask=riversRef.putFile(file)// Register observers to listen for when the download is done or if it failsuploadTask.addOnFailureListener{// Handle unsuccessful uploads}.addOnSuccessListener{taskSnapshot->// taskSnapshot.metadata contains file metadata such as size, content-type, etc.// ...}
Urifile=Uri.fromFile(newFile("path/to/images/rivers.jpg"));StorageReferenceriversRef=storageRef.child("images/"+file.getLastPathSegment());uploadTask=riversRef.putFile(file);// Register observers to listen for when the download is done or if it failsuploadTask.addOnFailureListener(newOnFailureListener(){@OverridepublicvoidonFailure(@NonNullExceptionexception){// Handle unsuccessful uploads}}).addOnSuccessListener(newOnSuccessListener<UploadTask.TaskSnapshot>(){@OverridepublicvoidonSuccess(UploadTask.TaskSnapshottaskSnapshot){// taskSnapshot.getMetadata() contains file metadata such as size, content-type, etc.// ...}});
finalStorageReferenceref=storageRef.child("images/mountains.jpg");uploadTask=ref.putFile(file);Task<Uri>urlTask=uploadTask.continueWithTask(newContinuation<UploadTask.TaskSnapshot,Task<Uri>>(){@OverridepublicTask<Uri>then(@NonNullTask<UploadTask.TaskSnapshot>task)throwsException{if(!task.isSuccessful()){throwtask.getException();}// Continue with the task to get the download URLreturnref.getDownloadUrl();}}).addOnCompleteListener(newOnCompleteListener<Uri>(){@OverridepublicvoidonComplete(@NonNullTask<Uri>task){if(task.isSuccessful()){UridownloadUri=task.getResult();}else{// Handle failures// ...}}});
You can also include metadata when you upload files.
This metadata contains typical file metadata properties such asname,size,
andcontentType(commonly referred to as MIME type). TheputFile()method
automatically infers the MIME type from theFileextension, but you can
override the auto-detected type by specifyingcontentTypein the metadata. If
you do not provide acontentTypeandCloud Storagecannot infer a
default from the file extension,Cloud Storageusesapplication/octet-stream. See theUse File Metadatasection for more information about file metadata.
Kotlin
// Create file metadata including the content typevarmetadata=storageMetadata{contentType="image/jpg"}// Upload the file and metadatauploadTask=storageRef.child("images/mountains.jpg").putFile(file,metadata)
// Create file metadata including the content typeStorageMetadatametadata=newStorageMetadata.Builder().setContentType("image/jpg").build();// Upload the file and metadatauploadTask=storageRef.child("images/mountains.jpg").putFile(file,metadata);
In addition to starting uploads, you can pause, resume, and cancel uploads using
thepause(),resume(), andcancel()methods. Pause and resume events
raisepauseandprogressstate changes respectively. Canceling an
upload causes the upload to fail with an error indicating that the
upload was canceled.
Kotlin
uploadTask=storageRef.child("images/mountains.jpg").putFile(file)// Pause the uploaduploadTask.pause()// Resume the uploaduploadTask.resume()// Cancel the uploaduploadTask.cancel()
uploadTask=storageRef.child("images/mountains.jpg").putFile(file);// Pause the uploaduploadTask.pause();// Resume the uploaduploadTask.resume();// Cancel the uploaduploadTask.cancel();
You can add listeners to handle success, failure, progress, or pauses in your
upload task:
Listener Type
Typical Usage
OnProgressListener
This listener is called periodically as data is transferred and can be used to populate an upload/download indicator.
OnPausedListener
This listener is called any time the task is paused.
OnSuccessListener
This listener is called when the task has successfully completed.
OnFailureListener
This listener is called any time the upload has failed. This can happen due to network timeouts, authorization failures, or if you cancel the task.
OnFailureListeneris called with anExceptioninstance. Other
listeners are called with anUploadTask.TaskSnapshotobject.
This object is an immutable view of the task at the time the event occurred.
AnUploadTask.TaskSnapshotcontains the following properties:
Property
Type
Description
getDownloadUrl
String
A URL that can be used to download the object. This is a public unguessable URL that can be shared with other clients. This value is populated once an upload is complete.
getError
Exception
If the task failed, this will have the cause as an Exception.
getBytesTransferred
long
The total number of bytes that have been transferred when this snapshot was taken.
getTotalByteCount
long
The total number of bytes expected to be uploaded.
getUploadSessionUri
String
A URI that can be used to continue this task via another call to putFile.
getMetadata
StorageMetadata
Before an upload completes, this is the metadata being sent to the server. After the upload completes, this is the metadata returned by the server.
getTask
UploadTask
The task that created this snapshot. Use this task to cancel, pause, or resume the upload.
getStorage
StorageReference
TheStorageReferenceused to create theUploadTask.
TheUploadTaskevent listeners provide a simple and powerful way to monitor
upload events.
Kotlin
// Observe state change events such as progress, pause, and resume// You'll need to import com.google.firebase.storage.component1 and// com.google.firebase.storage.component2uploadTask.addOnProgressListener{(bytesTransferred,totalByteCount)->valprogress=(100.0*bytesTransferred)/totalByteCountLog.d(TAG,"Upload is$progress% done")}.addOnPausedListener{Log.d(TAG,"Upload is paused")}
// Observe state change events such as progress, pause, and resumeuploadTask.addOnProgressListener(newOnProgressListener<UploadTask.TaskSnapshot>(){@OverridepublicvoidonProgress(UploadTask.TaskSnapshottaskSnapshot){doubleprogress=(100.0*taskSnapshot.getBytesTransferred())/taskSnapshot.getTotalByteCount();Log.d(TAG,"Upload is "+progress+"% done");}}).addOnPausedListener(newOnPausedListener<UploadTask.TaskSnapshot>(){@OverridepublicvoidonPaused(UploadTask.TaskSnapshottaskSnapshot){Log.d(TAG,"Upload is paused");}});
Uploads continue in the background even afteractivity lifecyclechanges (such
as presenting a dialog or rotating the screen). Any listeners you had attached
will also remain attached. This could cause unexpected results if they get
called after the activity is stopped.
You can solve this problem by subscribing your listeners with an activity scope
to automatically unregister them when the activity stops. Then, use thegetActiveUploadTasksmethod when the activity restarts to obtain upload tasks
that are still running or recently completed.
The example below demonstrates this and also shows how to persist the storage
reference path used.
Kotlin
overridefunonSaveInstanceState(outState:Bundle){super.onSaveInstanceState(outState)// If there's an upload in progress, save the reference so you can query it lateroutState.putString("reference",storageRef.toString())}overridefunonRestoreInstanceState(savedInstanceState:Bundle){super.onRestoreInstanceState(savedInstanceState)// If there was an upload in progress, get its reference and create a new StorageReferencevalstringRef=savedInstanceState.getString("reference")?:returnstorageRef=Firebase.storage.getReferenceFromUrl(stringRef)// Find all UploadTasks under this StorageReference (in this example, there should be one)valtasks=storageRef.activeUploadTasksif(tasks.size>0){// Get the task monitoring the uploadvaltask=tasks[0]// Add new listeners to the task using an Activity scopetask.addOnSuccessListener(this){// Success!// ...}}}
@OverrideprotectedvoidonSaveInstanceState(BundleoutState){super.onSaveInstanceState(outState);// If there's an upload in progress, save the reference so you can query it laterif(mStorageRef!=null){outState.putString("reference",mStorageRef.toString());}}@OverrideprotectedvoidonRestoreInstanceState(BundlesavedInstanceState){super.onRestoreInstanceState(savedInstanceState);// If there was an upload in progress, get its reference and create a new StorageReferencefinalStringstringRef=savedInstanceState.getString("reference");if(stringRef==null){return;}mStorageRef=FirebaseStorage.getInstance().getReferenceFromUrl(stringRef);// Find all UploadTasks under this StorageReference (in this example, there should be one)List<UploadTask>tasks=mStorageRef.getActiveUploadTasks();if(tasks.size()>0){// Get the task monitoring the uploadUploadTasktask=tasks.get(0);// Add new listeners to the task using an Activity scopetask.addOnSuccessListener(this,newOnSuccessListener<UploadTask.TaskSnapshot>(){@OverridepublicvoidonSuccess(UploadTask.TaskSnapshotstate){// Success!// ...}});}}
getActiveUploadTasksretrieves all active upload tasks at and below the
provided reference, so you may need to handle multiple tasks.
Continuing Uploads Across Process Restarts
If your process is shut down, any uploads in progress will be interrupted.
However, you can continue uploading once the process restarts by resuming the
upload session with the server. This can save time and bandwidth by not
starting the upload from the start of the file.
To do this, begin uploading viaputFile. On the resultingStorageTask,
callgetUploadSessionUriand save the resulting value in persistent storage
(such as SharedPreferences).
Kotlin
uploadTask=storageRef.putFile(localFile)uploadTask.addOnProgressListener{taskSnapshot->sessionUri=taskSnapshot.uploadSessionUriif(sessionUri!=null&&!saved){saved=true// A persisted session has begun with the server.// Save this to persistent storage in case the process dies.}}
uploadTask=mStorageRef.putFile(localFile);uploadTask.addOnProgressListener(newOnProgressListener<UploadTask.TaskSnapshot>(){@OverridepublicvoidonProgress(UploadTask.TaskSnapshottaskSnapshot){UrisessionUri=taskSnapshot.getUploadSessionUri();if(sessionUri!=null&&!mSaved){mSaved=true;// A persisted session has begun with the server.// Save this to persistent storage in case the process dies.}}});
After your process restarts with an interrupted upload, call putFile again. But
this time also pass the Uri that was saved.
Kotlin
// resume the upload task from where it left off when the process died.// to do this, pass the sessionUri as the last parameteruploadTask=storageRef.putFile(localFile,storageMetadata{},sessionUri,)
//resume the upload task from where it left off when the process died.//to do this, pass the sessionUri as the last parameteruploadTask=mStorageRef.putFile(localFile,newStorageMetadata.Builder().build(),sessionUri);
Sessions last one week. If you attempt to resume a session after it has
expired or if it had experienced an error, you will receive a failure callback.
It is your responsibility to ensure the file has not changed between uploads.
Error Handling
There are a number of reasons why errors may occur on upload, including
the local file not existing, or the user not having permission to upload
the desired file. You can find more information about errors in theHandle Errorssection of the docs.
Full Example
A full example of an upload with progress monitoring and error handling
is shown below:
Kotlin
// File or Blobfile=Uri.fromFile(File("path/to/mountains.jpg"))// Create the file metadatametadata=storageMetadata{contentType="image/jpeg"}// Upload file and metadata to the path 'images/mountains.jpg'uploadTask=storageRef.child("images/${file.lastPathSegment}").putFile(file,metadata)// Listen for state changes, errors, and completion of the upload.// You'll need to import com.google.firebase.storage.component1 and// com.google.firebase.storage.component2uploadTask.addOnProgressListener{(bytesTransferred,totalByteCount)->valprogress=(100.0*bytesTransferred)/totalByteCountLog.d(TAG,"Upload is$progress% done")}.addOnPausedListener{Log.d(TAG,"Upload is paused")}.addOnFailureListener{// Handle unsuccessful uploads}.addOnSuccessListener{// Handle successful uploads on complete// ...}
// File or Blobfile=Uri.fromFile(newFile("path/to/mountains.jpg"));// Create the file metadatametadata=newStorageMetadata.Builder().setContentType("image/jpeg").build();// Upload file and metadata to the path 'images/mountains.jpg'uploadTask=storageRef.child("images/"+file.getLastPathSegment()).putFile(file,metadata);// Listen for state changes, errors, and completion of the upload.uploadTask.addOnProgressListener(newOnProgressListener<UploadTask.TaskSnapshot>(){@OverridepublicvoidonProgress(UploadTask.TaskSnapshottaskSnapshot){doubleprogress=(100.0*taskSnapshot.getBytesTransferred())/taskSnapshot.getTotalByteCount();Log.d(TAG,"Upload is "+progress+"% done");}}).addOnPausedListener(newOnPausedListener<UploadTask.TaskSnapshot>(){@OverridepublicvoidonPaused(UploadTask.TaskSnapshottaskSnapshot){Log.d(TAG,"Upload is paused");}}).addOnFailureListener(newOnFailureListener(){@OverridepublicvoidonFailure(@NonNullExceptionexception){// Handle unsuccessful uploads}}).addOnSuccessListener(newOnSuccessListener<UploadTask.TaskSnapshot>(){@OverridepublicvoidonSuccess(UploadTask.TaskSnapshottaskSnapshot){// Handle successful uploads on complete// ...}});
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-09-04 UTC."],[],[],null,[]]