Firebase Summit で発表されたすべての情報をご覧ください。Firebase を使用してアプリ開発を加速し、自信を持ってアプリを実行する方法を紹介しています。詳細

AndroidのCloudStorageでファイルをアップロードする

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

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( 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( 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 で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
            // ...
        }
    }
});

ファイル メタデータの追加

ファイルをアップロードするときにメタデータを含めることもできます。このメタデータには、 namesizecontentType (一般に 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()メソッドを使用して、アップロードを一時停止、再開、およびキャンセルできます。一時停止イベントと再開イベントは、 pauseprogress状況の変更をそれぞれ発生させます。アップロードをキャンセルすると、アップロードがキャンセルされたことを示すエラーでアップロードが失敗します。

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このリスナーは、アップロードが失敗するたびに呼び出されます。これは、ネットワークのタイムアウト、承認の失敗、またはタスクをキャンセルした場合に発生する可能性があります。

OnFailureListenerExceptionインスタンスで呼び出されます。他のリスナーはUploadTask.TaskSnapshotオブジェクトで呼び出されます。このオブジェクトは、イベント発生時のタスクの不変ビューです。 UploadTask.TaskSnapshotには、次のプロパティが含まれています。

財産タイプ説明
getDownloadUrl Stringオブジェクトのダウンロードに使用できる URL。これは、他のクライアントと共有できる公開された推測不可能な URL です。この値は、アップロードが完了すると入力されます。
getError Exceptionタスクが失敗した場合、これには例外として原因があります。
getBytesTransferred longこのスナップショットが作成されたときに転送された合計バイト数。
getTotalByteCount longアップロードされると予想される合計バイト数。
getUploadSessionUri String putFile への別の呼び出しを介してこのタスクを続行するために使用できる URI。
getMetadata StorageMetadataアップロードが完了する前に、これはサーバーに送信されるメタデータです。アップロードが完了すると、これがサーバーから返されるメタデータです。
getTask UploadTaskこのスナップショットを作成したタスク。このタスクを使用して、アップロードをキャンセル、一時停止、または再開します。
getStorage StorageReference StorageReferenceの作成に使用されるUploadTask

UploadTaskイベント リスナーは、アップロード イベントを監視するためのシンプルで強力な方法を提供します。

Kotlin+KTX

// Observe state change events such as progress, pause, and resume
// You'll need to import com.google.firebase.storage.ktx.component1 and 
// com.google.firebase.storage.ktx.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を介してアップロードを開始します。結果のStorageTaskgetUploadSessionUriを呼び出し、結果の値を永続ストレージ (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 を呼び出します。でも今回も救われたウリを渡す。

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.ktx.component1 and 
// com.google.firebase.storage.ktx.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 からファイルをダウンロードする方法を学びましょう。