Cloud Storage for Firebase を使用すると、Firebase によって提供、管理される Cloud Storage バケットにファイルを迅速かつ容易にアップロードできます。
ファイルのアップロード
ファイルを Cloud Storage にアップロードするには、まずファイル名を含むファイルのフルパスへの参照を作成します。
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
適切な参照を作成したら、putBytes()
、putFile()
、または putStream()
メソッドを呼び出して、Cloud Storage にファイルをアップロードできます。
Cloud Storage バケットのルートへの参照を指定してデータをアップロードすることはできません。参照は子 URL を指し示す必要があります。
メモリ内のデータからアップロードする
putBytes()
メソッドは、Cloud Storage にファイルをアップロードする最も簡単な方法です。putBytes()
は byte[]
を受け取って UploadTask
を返します。これを使用してアップロード ステータスを管理、モニタリングできます。
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. // ... } });
putBytes()
は byte[]
を受け取るため、アプリはファイルのコンテンツ全体を一度にメモリ内に保持する必要があります。使用するメモリを少なくするには、putStream()
または putFile()
を使用します。
ストリームからアップロードする
putStream()
メソッドは、ファイルを Cloud Storage にアップロードするうえで最も用途の広い方法です。putStream()
は InputStream
を受け取って UploadTask
を返します。これを使用してアップロード ステータスを管理、モニタリングできます。
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. // ... } });
ローカル ファイルからアップロードする
写真や動画などのデバイス上のローカル ファイルは、putFile()
メソッドを使用してアップロードできます。putFile()
は File
を受け取って UploadTask
を返します。これを使用してアップロード ステータスを管理、モニタリングできます。
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. // ... } });
ダウンロード URL を取得する
ファイルをアップロードした後、StorageReference
で getDownloadUrl()
メソッドを呼び出して、ファイルをダウンロードするための URL を取得できます。
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 // ... } } });
ファイル メタデータを追加する
ファイルをアップロードするときにメタデータを含めることもできます。このメタデータには、name
、size
、contentType
(一般的に MIME タイプと呼ばれます)などの標準的なファイル メタデータのプロパティが含まれます。putFile()
メソッドでは File
拡張子から MIME タイプが自動的に推測されますが、contentType
をメタデータに指定することにより、自動検出されるタイプをオーバーライドできます。contentType
が指定されず、Cloud Storage がファイル拡張子からデフォルトのコンテンツ タイプを自動的に推測することもできない場合は、Cloud Storage は application/octet-stream
を使用します。ファイル メタデータの詳細については、ファイル メタデータの使用のセクションをご覧ください。
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);
アップロードを管理する
アップロードを開始するだけでなく、pause()
、resume()
、cancel()
メソッドを使ってアップロードを一時停止、再開、キャンセルすることもできます。イベントを一時停止するとステータスが pause
に変わり、イベントを再開するとステータスが progress
に変わります。アップロードをキャンセルするとアップロードが失敗し、アップロードがキャンセルされたことを示すエラーが返されます。
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();
アップロードの進捗状況をモニタリングする
アップロード タスクの成功、失敗、進捗状況、一時停止を処理するためのリスナーを追加することができます。
リスナーのタイプ | 一般的な使用方法 |
---|---|
OnProgressListener |
データが転送されると定期的に呼び出され、アップロードまたはダウンロードのインジケータを埋め込むために使用できます。 |
OnPausedListener |
タスクが一時停止されると呼び出されます。 |
OnSuccessListener |
タスクが正常に完了すると呼び出されます。 |
OnFailureListener |
アップロードが失敗すると呼び出されます。アップロードの失敗は、ネットワークのタイムアウトや認証の失敗が原因で発生します。またはタスクをキャンセルした場合にも発生します。 |
OnFailureListener
は Exception
インスタンスとともに呼び出されます。その他のリスナーは、UploadTask.TaskSnapshot
オブジェクトとともに呼び出されます。このオブジェクトは、イベントが発生したときのタスクの不変のビューです。UploadTask.TaskSnapshot
には、以下のプロパティが含まれます。
プロパティ | タイプ | 説明 |
---|---|---|
getDownloadUrl |
String |
オブジェクトのダウンロードに使用できる URL です。これは他のクライアントと共有できる、推測不可能な公開 URL です。この値はアップロードが完了すると入力されます。 |
getError |
Exception |
タスクが失敗した場合に、原因を例外にします。 |
getBytesTransferred |
long |
このスナップショットが作成された時点で転送済みのバイト数の合計です。 |
getTotalByteCount |
long |
アップロードされる予定のバイト数の合計です。 |
getUploadSessionUri |
String |
putFile の別の呼び出しを使ってこのタスクを続行する場合に使用できる URI です。 |
getMetadata |
StorageMetadata |
アップロードが完了する前にサーバーに送信されているメタデータです。アップロードが完了した後でサーバーから返されるメタデータです。 |
getTask |
UploadTask |
このスナップショットを作成したタスクです。このタスクを使用して、アップロードをキャンセル、一時停止、または再開します。 |
getStorage |
StorageReference |
UploadTask の作成に使用される StorageReference 。 |
UploadTask
イベント リスナーを使うことで、アップロード イベントを簡単かつ効果的にモニタリングできます。
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"); } });
アクティビティのライフサイクルの変更を処理する
アクティビティのライフサイクル(ダイアログの表示や画面の回転など)が変わった後でも、アップロードはバックグラウンドで継続します。アタッチしたリスナーも、アタッチされたまま維持されます。このため、アクティビティが停止した後でリスナーが呼び出されると、予期せぬ結果が生じることがあります。
この問題を解決するには、アクティビティの範囲を指定してリスナーを登録します。こうすると、そのアクティビティが停止したときにリスナーは自動的に登録を解除されます。次に、アクティビティが再開したら getActiveUploadTasks
メソッドを使用して、実行中または最近完了したアップロード タスクを取得します。
以下の例は、上記の手順と、使用するストレージ参照パスを保持する方法を示しています。
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! // ... } }); } }
getActiveUploadTasks
では、指定した参照とその下にある有効なアップロード タスクがすべて取得されるため、複数のタスクの処理が必要になる場合があります。
プロセス再開後のアップロードの続行
プロセスがシャットダウンされると、進行中のアップロードも中断されます。 ただし、プロセスが再開したら、サーバーでアップロード セッションを再開することでアップロードを続行できます。つまりファイルの最初からアップロードを開始しないため、時間と帯域幅を節約できます。
この手法を実施するには、putFile
を使用してアップロードを開始します。StorageTask
の結果が返されたら getUploadSessionUri
を呼び出して、結果の値を永続ストレージ(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. } } });
プロセスと中断されたアップロードが再開したら、putFile をもう一度呼び出します。ただし、今回は保存された URI も渡します。
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);
セッションは 1 週間維持されます。セッションの期限が切れた後でセッションを再開しようとした場合、またはエラーが発生した場合は、失敗のコールバックを受け取ります。アップロードの間にファイルが変更されていないことを必ずご確認ください。
エラー処理
アップロード時にエラーが発生する理由として、ローカル ファイルが存在しない、目的のファイルをアップロードする権限がユーザーにないなど、たくさんの理由が考えられます。エラーについて詳しくは、このドキュメントのエラーの処理のセクションをご覧ください。
例
アップロード、進捗状況のモニタリング、エラー処理の完全な例を以下に示します。
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 // ... } });
これでファイルのアップロードが完了しました。次は、Cloud Storage からファイルをダウンロードする方法を学習しましょう。