Dateien mit Cloud Storage auf Android-Geräten hochladen

Mit Cloud Storage for Firebase können Sie schnell und einfach Dateien in einen von Firebase bereitgestellten und verwalteten Bucket Cloud Storage hochladen.

Dateien hochladen

Wenn Sie eine Datei in Cloud Storage hochladen möchten, erstellen Sie zuerst einen Verweis auf den vollständigen Pfad der Datei, einschließlich des Dateinamens.

Kotlin+KTX

// Create a storage reference from our app
val storageRef = storage.reference

// Create a reference to "mountains.jpg"
val mountainsRef = storageRef.child("mountains.jpg")

// Create a reference to 'images/mountains.jpg'
val mountainImagesRef = storageRef.child("images/mountains.jpg")

// While the file names are the same, the references point to different files
mountainsRef.name == mountainImagesRef.name // true
mountainsRef.path == mountainImagesRef.path // false

Java

// Create a storage reference from our app
StorageReference storageRef = storage.getReference();

// Create a reference to "mountains.jpg"
StorageReference mountainsRef = storageRef.child("mountains.jpg");

// Create a reference to 'images/mountains.jpg'
StorageReference mountainImagesRef = storageRef.child("images/mountains.jpg");

// While the file names are the same, the references point to different files
mountainsRef.getName().equals(mountainImagesRef.getName());    // true
mountainsRef.getPath().equals(mountainImagesRef.getPath());    // false

Nachdem Sie eine entsprechende Referenz erstellt haben, rufen Sie die Methode putBytes(), putFile() oder putStream() auf, um die Datei in Cloud Storage hochzuladen.

Sie können keine Daten mit einer Referenz auf die Wurzel Ihres Cloud Storage-Buckets hochladen. Die Referenz muss auf eine untergeordnete URL verweisen.

Aus Daten im Arbeitsspeicher hochladen

Die putBytes()-Methode ist die einfachste Möglichkeit, eine Datei in Cloud Storage hochzuladen. putBytes() nimmt eine byte[] entgegen und gibt eine UploadTask zurück, mit der du den Status des Uploads verwalten und beobachten kannst.

Kotlin+KTX

// Get the data from an ImageView as bytes
imageView.isDrawingCacheEnabled = true
imageView.buildDrawingCache()
val bitmap = (imageView.drawable as BitmapDrawable).bitmap
val baos = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)
val data = baos.toByteArray()

var uploadTask = mountainsRef.putBytes(data)
uploadTask.addOnFailureListener {
    // Handle unsuccessful uploads
}.addOnSuccessListener { taskSnapshot ->
    // taskSnapshot.metadata contains file metadata such as size, content-type, etc.
    // ...
}

Java

// Get the data from an ImageView as bytes
imageView.setDrawingCacheEnabled(true);
imageView.buildDrawingCache();
Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] data = baos.toByteArray();

UploadTask uploadTask = mountainsRef.putBytes(data);
uploadTask.addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception exception) {
        // Handle unsuccessful uploads
    }
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
    @Override
    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
        // taskSnapshot.getMetadata() contains file metadata such as size, content-type, etc.
        // ...
    }
});

Da putBytes() eine byte[] akzeptiert, muss Ihre App den gesamten Inhalt einer Datei gleichzeitig im Arbeitsspeicher halten. Verwenden Sie stattdessen putStream() oder putFile(), um weniger Arbeitsspeicher zu verbrauchen.

Über einen Stream hochladen

Die putStream()-Methode ist die vielseitigste Möglichkeit, eine Datei in Cloud Storage hochzuladen. putStream() nimmt einen InputStream als Argument und gibt einen UploadTask zurück, mit dem Sie den Status des Uploads verwalten und überwachen können.

Kotlin+KTX

val stream = 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.
    // ...
}

Java

InputStream stream = new FileInputStream(new File("path/to/images/rivers.jpg"));

uploadTask = mountainsRef.putStream(stream);
uploadTask.addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception exception) {
        // Handle unsuccessful uploads
    }
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
    @Override
    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
        // taskSnapshot.getMetadata() contains file metadata such as size, content-type, etc.
        // ...
    }
});

Von einer lokalen Datei hochladen

Mit der Methode putFile() können Sie lokale Dateien wie Fotos und Videos von der Kamera auf das Gerät hochladen. putFile() nimmt eine File entgegen und gibt eine UploadTask zurück, mit der du den Status des Uploads verwalten und beobachten kannst.

Kotlin+KTX

var file = Uri.fromFile(File("path/to/images/rivers.jpg"))
val riversRef = storageRef.child("images/${file.lastPathSegment}")
uploadTask = riversRef.putFile(file)

// Register observers to listen for when the download is done or if it fails
uploadTask.addOnFailureListener {
    // Handle unsuccessful uploads
}.addOnSuccessListener { taskSnapshot ->
    // taskSnapshot.metadata contains file metadata such as size, content-type, etc.
    // ...
}

Java

Uri file = Uri.fromFile(new File("path/to/images/rivers.jpg"));
StorageReference riversRef = storageRef.child("images/"+file.getLastPathSegment());
uploadTask = riversRef.putFile(file);

// Register observers to listen for when the download is done or if it fails
uploadTask.addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception exception) {
        // Handle unsuccessful uploads
    }
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
    @Override
    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
        // taskSnapshot.getMetadata() contains file metadata such as size, content-type, etc.
        // ...
    }
});

Download-URL abrufen

Nachdem du eine Datei hochgeladen hast, kannst du eine URL zum Herunterladen der Datei abrufen, indem du die getDownloadUrl()-Methode auf der StorageReference aufrufst:

Kotlin+KTX

val ref = storageRef.child("images/mountains.jpg")
uploadTask = ref.putFile(file)

val urlTask = uploadTask.continueWithTask { task ->
    if (!task.isSuccessful) {
        task.exception?.let {
            throw it
        }
    }
    ref.downloadUrl
}.addOnCompleteListener { task ->
    if (task.isSuccessful) {
        val downloadUri = task.result
    } else {
        // Handle failures
        // ...
    }
}

Java

final StorageReference ref = storageRef.child("images/mountains.jpg");
uploadTask = ref.putFile(file);

Task<Uri> urlTask = uploadTask.continueWithTask(new Continuation<UploadTask.TaskSnapshot, Task<Uri>>() {
    @Override
    public Task<Uri> then(@NonNull Task<UploadTask.TaskSnapshot> task) throws Exception {
        if (!task.isSuccessful()) {
            throw task.getException();
        }

        // Continue with the task to get the download URL
        return ref.getDownloadUrl();
    }
}).addOnCompleteListener(new OnCompleteListener<Uri>() {
    @Override
    public void onComplete(@NonNull Task<Uri> task) {
        if (task.isSuccessful()) {
            Uri downloadUri = task.getResult();
        } else {
            // Handle failures
            // ...
        }
    }
});

Dateimetadaten hinzufügen

Sie können auch Metadaten beim Hochladen von Dateien angeben. Diese Metadaten enthalten typische Dateimetadateneigenschaften wie name, size und contentType (allgemein als MIME-Typ bezeichnet). Bei der putFile()-Methode wird der MIME-Typ automatisch anhand der File-Erweiterung abgeleitet. Sie können den automatisch erkannten Typ jedoch überschreiben, indem Sie in den Metadaten contentType angeben. Wenn Sie keine contentType angeben und Cloud Storage keine Standardeinstellung aus der Dateiendung ableiten kann, verwendet Cloud Storage application/octet-stream. Weitere Informationen zu Dateimetadaten finden Sie im Abschnitt Dateimetadaten verwenden.

Kotlin+KTX

// Create file metadata including the content type
var metadata = storageMetadata {
    contentType = "image/jpg"
}

// Upload the file and metadata
uploadTask = storageRef.child("images/mountains.jpg").putFile(file, metadata)

Java

// Create file metadata including the content type
StorageMetadata metadata = new StorageMetadata.Builder()
        .setContentType("image/jpg")
        .build();

// Upload the file and metadata
uploadTask = storageRef.child("images/mountains.jpg").putFile(file, metadata);

Uploads verwalten

Mit den Methoden pause(), resume() und cancel() können Sie Uploads nicht nur starten, sondern auch pausieren, fortsetzen und abbrechen. Pausieren- und Fortsetzen-Ereignisse lösen jeweils Statusänderungen von pause und progress aus. Wenn Sie einen Upload abbrechen, schlägt er fehl und Sie erhalten eine Fehlermeldung, dass der Upload abgebrochen wurde.

Kotlin+KTX

uploadTask = storageRef.child("images/mountains.jpg").putFile(file)

// Pause the upload
uploadTask.pause()

// Resume the upload
uploadTask.resume()

// Cancel the upload
uploadTask.cancel()

Java

uploadTask = storageRef.child("images/mountains.jpg").putFile(file);

// Pause the upload
uploadTask.pause();

// Resume the upload
uploadTask.resume();

// Cancel the upload
uploadTask.cancel();

Uploadfortschritt im Blick behalten

Sie können Listener hinzufügen, um den Erfolg, den Fehler, den Fortschritt oder die Pausen bei der Uploadaufgabe zu verarbeiten:

Listener-Typ Typische Verwendung
OnProgressListener Dieser Listener wird bei der Datenübertragung regelmäßig aufgerufen und kann zum Ausfüllen eines Upload-/Download-Indikators verwendet werden.
OnPausedListener Dieser Listener wird immer dann aufgerufen, wenn die Aufgabe pausiert wird.
OnSuccessListener Dieser Listener wird aufgerufen, wenn die Aufgabe erfolgreich abgeschlossen wurde.
OnFailureListener Dieser Listener wird immer dann aufgerufen, wenn der Upload fehlgeschlagen ist. Das kann auf Netzwerkzeitüberschreitungen, Autorisierungsfehler oder den Abbruch der Aufgabe zurückzuführen sein.

OnFailureListener wird mit einer Exception-Instanz aufgerufen. Andere Listener werden mit einem UploadTask.TaskSnapshot-Objekt aufgerufen. Dieses Objekt ist eine unveränderliche Ansicht der Aufgabe zum Zeitpunkt des Ereignisses. Ein UploadTask.TaskSnapshot enthält die folgenden Eigenschaften:

Attribut Typ Beschreibung
getDownloadUrl String Eine URL, über die das Objekt heruntergeladen werden kann. Dies ist eine öffentliche, nicht ermittelbare URL, die mit anderen Kunden geteilt werden kann. Dieser Wert wird ausgefüllt, sobald ein Upload abgeschlossen ist.
getError Exception Wenn die Aufgabe fehlgeschlagen ist, wird dies als Ausnahme angegeben.
getBytesTransferred long Die Gesamtzahl der Bytes, die zum Zeitpunkt der Erstellung dieses Snapshots übertragen wurden.
getTotalByteCount long Die Gesamtzahl der Byte, die voraussichtlich hochgeladen werden.
getUploadSessionUri String Ein URI, mit dem diese Aufgabe über einen weiteren Aufruf von putFile fortgesetzt werden kann.
getMetadata StorageMetadata Bevor ein Upload abgeschlossen ist, werden diese Metadaten an den Server gesendet. Nach Abschluss des Uploads werden diese Metadaten vom Server zurückgegeben.
getTask UploadTask Die Aufgabe, mit der dieser Snapshot erstellt wurde. Mit dieser Aufgabe können Sie den Upload abbrechen, pausieren oder fortsetzen.
getStorage StorageReference Die StorageReference, mit der die UploadTask erstellt wurde.

Die UploadTask-Ereignis-Listener bieten eine einfache und leistungsstarke Möglichkeit, Uploadereignisse zu überwachen.

Kotlin+KTX

// 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.component2
uploadTask.addOnProgressListener { (bytesTransferred, totalByteCount) ->
    val progress = (100.0 * bytesTransferred) / totalByteCount
    Log.d(TAG, "Upload is $progress% done")
}.addOnPausedListener {
    Log.d(TAG, "Upload is paused")
}

Java

// Observe state change events such as progress, pause, and resume
uploadTask.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
    @Override
    public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
        double progress = (100.0 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount();
        Log.d(TAG, "Upload is " + progress + "% done");
    }
}).addOnPausedListener(new OnPausedListener<UploadTask.TaskSnapshot>() {
    @Override
    public void onPaused(UploadTask.TaskSnapshot taskSnapshot) {
        Log.d(TAG, "Upload is paused");
    }
});

Änderungen am Aktivitätslebenszyklus verarbeiten

Uploads werden im Hintergrund fortgesetzt, auch wenn sich der Aktivitätslebenszyklus ändert, z. B. wenn ein Dialogfeld angezeigt oder der Bildschirm gedreht wird. Alle zuvor hinzugefügten Listener bleiben ebenfalls erhalten. Das kann zu unerwarteten Ergebnissen führen, wenn sie nach dem Beenden der Aktivität aufgerufen werden.

Sie können dieses Problem beheben, indem Sie Ihre Listener mit einem Aktivitätsbereich abonnieren, damit sie automatisch abgemeldet werden, wenn die Aktivität beendet wird. Verwende dann die Methode getActiveUploadTasks, wenn die Aktivität neu gestartet wird, um Uploadaufgaben abzurufen, die noch ausgeführt werden oder vor Kurzem abgeschlossen wurden.

Das folgende Beispiel veranschaulicht dies und zeigt auch, wie der verwendete Speicherreferenzpfad beibehalten wird.

Kotlin+KTX

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)

    // If there's an upload in progress, save the reference so you can query it later
    outState.putString("reference", storageRef.toString())
}

override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)

    // If there was an upload in progress, get its reference and create a new StorageReference
    val stringRef = savedInstanceState.getString("reference") ?: return

    storageRef = Firebase.storage.getReferenceFromUrl(stringRef)

    // Find all UploadTasks under this StorageReference (in this example, there should be one)

    val tasks = storageRef.activeUploadTasks

    if (tasks.size > 0) {
        // Get the task monitoring the upload
        val task = tasks[0]

        // Add new listeners to the task using an Activity scope
        task.addOnSuccessListener(this) {
            // Success!
            // ...
        }
    }
}

Java

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    // If there's an upload in progress, save the reference so you can query it later
    if (mStorageRef != null) {
        outState.putString("reference", mStorageRef.toString());
    }
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);

    // If there was an upload in progress, get its reference and create a new StorageReference
    final String stringRef = 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 upload
        UploadTask task = tasks.get(0);

        // Add new listeners to the task using an Activity scope
        task.addOnSuccessListener(this, new OnSuccessListener<UploadTask.TaskSnapshot>() {
            @Override
            public void onSuccess(UploadTask.TaskSnapshot state) {
                // Success!
                // ...
            }
        });
    }
}

Mit getActiveUploadTasks werden alle aktiven Uploadaufgaben ab der angegebenen Referenz abgerufen. Möglicherweise müssen Sie also mehrere Aufgaben bearbeiten.

Uploads bei Prozessneustarts fortsetzen

Wenn der Prozess beendet wird, werden alle laufenden Uploads unterbrochen. Sie können den Upload jedoch fortsetzen, sobald der Prozess neu gestartet wurde, indem Sie die Uploadsitzung mit dem Server fortsetzen. Dadurch können Sie Zeit und Bandbreite sparen, da der Upload nicht von Anfang an gestartet wird.

Starten Sie dazu den Upload über putFile. Rufen Sie für die resultierende StorageTask getUploadSessionUri auf und speichern Sie den resultierenden Wert im dauerhaften Speicher (z. B. SharedPreferences).

Kotlin+KTX

uploadTask = storageRef.putFile(localFile)
uploadTask.addOnProgressListener { taskSnapshot ->
    sessionUri = taskSnapshot.uploadSessionUri
    if (sessionUri != null && !saved) {
        saved = true
        // A persisted session has begun with the server.
        // Save this to persistent storage in case the process dies.
    }
}

Java

uploadTask = mStorageRef.putFile(localFile);
uploadTask.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
    @Override
    public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
        Uri sessionUri = 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.
        }
    }
});

Nachdem der Prozess mit einem unterbrochenen Upload neu gestartet wurde, rufen Sie putFile noch einmal auf. Geben Sie diesmal aber auch den gespeicherten URI an.

Kotlin+KTX

// resume the upload task from where it left off when the process died.
// to do this, pass the sessionUri as the last parameter
uploadTask = storageRef.putFile(
    localFile,
    storageMetadata { },
    sessionUri,
)

Java

//resume the upload task from where it left off when the process died.
//to do this, pass the sessionUri as the last parameter
uploadTask = mStorageRef.putFile(localFile,
        new StorageMetadata.Builder().build(), sessionUri);

Sitzungen dauern eine Woche. Wenn Sie versuchen, eine Sitzung fortzusetzen, nachdem sie abgelaufen ist oder ein Fehler aufgetreten ist, erhalten Sie einen Fehler-Callback. Sie müssen dafür sorgen, dass sich die Datei zwischen den Uploads nicht geändert hat.

Fehlerbehandlung

Es kann verschiedene Gründe für Fehler beim Upload geben, z. B. dass die lokale Datei nicht vorhanden ist oder der Nutzer keine Berechtigung zum Hochladen der gewünschten Datei hat. Weitere Informationen zu Fehlern finden Sie im Abschnitt Fehler beheben.

Vollständiges Beispiel

Unten siehst du ein vollständiges Beispiel für einen Upload mit Fortschrittsüberwachung und Fehlerbehandlung:

Kotlin+KTX

// File or Blob
file = Uri.fromFile(File("path/to/mountains.jpg"))

// Create the file metadata
metadata = 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.component2
uploadTask.addOnProgressListener { (bytesTransferred, totalByteCount) ->
    val progress = (100.0 * bytesTransferred) / totalByteCount
    Log.d(TAG, "Upload is $progress% done")
}.addOnPausedListener {
    Log.d(TAG, "Upload is paused")
}.addOnFailureListener {
    // Handle unsuccessful uploads
}.addOnSuccessListener {
    // Handle successful uploads on complete
    // ...
}

Java

// File or Blob
file = Uri.fromFile(new File("path/to/mountains.jpg"));

// Create the file metadata
metadata = new StorageMetadata.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(new OnProgressListener<UploadTask.TaskSnapshot>() {
    @Override
    public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
        double progress = (100.0 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount();
        Log.d(TAG, "Upload is " + progress + "% done");
    }
}).addOnPausedListener(new OnPausedListener<UploadTask.TaskSnapshot>() {
    @Override
    public void onPaused(UploadTask.TaskSnapshot taskSnapshot) {
        Log.d(TAG, "Upload is paused");
    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception exception) {
        // Handle unsuccessful uploads
    }
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
    @Override
    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
        // Handle successful uploads on complete
        // ...
    }
});

Nachdem Sie Dateien hochgeladen haben, erfahren Sie nun, wie Sie sie von Cloud Storage herunterladen.