[Firebase] uploadBytesのエラー処理
Cloud Storage for FirebaseのuploadBytesのエラー処理方法をコード例を含めて教えてください。
Cloud Storage for FirebaseのuploadBytesメソッドは、指定したパスにバイトデータをアップロードするために使用されます。アップロード時に発生する可能性のあるエラーを処理するために、以下のようなコード例をご紹介します。
// Firebaseストレージのインスタンスを取得 StorageReference storageRef = FirebaseStorage.getInstance().getReference(); // アップロードするファイルのパスを指定 String filePath = "images/photo.jpg"; // ファイルのバイトデータを作成 byte[] fileData = "This is a sample file.".getBytes(); // ストレージにバイトデータをアップロード storageRef.child(filePath).putBytes(fileData) .addOnSuccessListener(taskSnapshot -> { // アップロード成功時の処理 // 例えば、成功メッセージを表示したり、他の処理を行ったりする System.out.println("ファイルのアップロードに成功しました。"); }) .addOnFailureListener(exception -> { // アップロード失敗時の処理 // エラーメッセージを表示したり、適切なエラーハンドリングを行ったりする System.err.println("ファイルのアップロード中にエラーが発生しました:" + exception.getMessage()); });
このコード例では、uploadBytesメソッドに対してaddOnSuccessListenerメソッドとaddOnFailureListenerメソッドを追加しています。addOnSuccessListenerメソッドでは、アップロードが成功した場合に呼び出されるコードを記述します。addOnFailureListenerメソッドでは、アップロードが失敗した場合に呼び出されるコードを記述します。
アップロード成功時には、ファイルのアップロードに成功した旨をメッセージとして表示しています。アップロード失敗時には、エラーメッセージを表示していますが、必要に応じて適切なエラーハンドリングを行ってください。
なお、上記のコードはJavaの例ですが、他の言語やプラットフォームにも同様の方法でエラー処理が可能です。
Firebase js sdkのバージョンが古いです。バージョン10以降を使ってuploadBytesのエラー処理について解説してください。
Firebase JavaScript SDKでは、バージョン10以降からはuploadBytes
メソッドではなく、put
メソッドを使用するようになりました。バージョン10以降のSDKでのエラー処理の方法を以下に示します。
// Firebaseストレージの参照を取得 const storageRef = firebase.storage().ref(); // アップロードするファイルのパスを指定 const filePath = 'images/photo.jpg'; // ファイルのバイトデータを作成 const fileData = 'This is a sample file.'; // ストレージにバイトデータをアップロード const uploadTask = storageRef.child(filePath).put(fileData); uploadTask .then((snapshot) => { // アップロード成功時の処理 // 例えば、成功メッセージを表示したり、他の処理を行ったりする console.log('ファイルのアップロードに成功しました。'); }) .catch((error) => { // アップロード失敗時の処理 // エラーメッセージを表示したり、適切なエラーハンドリングを行ったりする console.error('ファイルのアップロード中にエラーが発生しました:', error); });
このコード例では、put
メソッドを使用してファイルのアップロードを行っています。put
メソッドはPromiseを返し、アップロードの結果を取得できます。
成功時には、Promiseのthen
メソッド内でアップロードが成功したことを示す処理を記述します。エラーが発生した場合には、catch
メソッド内でエラーメッセージを表示する処理を記述します。
なお、上記のコードはJavaScriptの例ですが、他の言語やプラットフォームでも同様の方法でエラー処理が可能です。使用しているFirebase SDKのバージョンに合ったドキュメントを参照して、適切な書き方を確認してください。
const result = await storageRef.child(filePath).put(fileData)
としたときの方法も教えてください。
await
キーワードを使用して非同期処理を同期的に扱う場合、try-catch文を使用してエラー処理を行う方法があります。以下にコード例を示します。
// Firebaseストレージの参照を取得 const storageRef = firebase.storage().ref(); // アップロードするファイルのパスを指定 const filePath = 'images/photo.jpg'; // ファイルのバイトデータを作成 const fileData = 'This is a sample file.'; try { const result = await storageRef.child(filePath).put(fileData); // アップロード成功時の処理 // 例えば、成功メッセージを表示したり、他の処理を行ったりする console.log('ファイルのアップロードに成功しました。'); } catch (error) { // アップロード失敗時の処理 // エラーメッセージを表示したり、適切なエラーハンドリングを行ったりする console.error('ファイルのアップロード中にエラーが発生しました:', error); }
await
キーワードは、非同期処理の結果が解決されるまで待機します。await
キーワードが使用される関数の前には、async
キーワードを付ける必要があります。
この例では、storageRef.child(filePath).put(fileData)
の結果をresult
変数に格納しています。アップロード成功時には、try
ブロック内のコードが実行されます。エラーが発生した場合には、catch
ブロック内のコードが実行されます。
await
キーワードを使用する場合は、エラーハンドリングを行うために必ずtry-catch
文を使用してください。
ドキュメントに書かれていた。
import { getStorage, ref, uploadBytesResumable, getDownloadURL } from "firebase/storage"; const storage = getStorage(); // Create the file metadata /** @type {any} */ const metadata = { contentType: 'image/jpeg' }; // Upload file and metadata to the object 'images/mountains.jpg' const storageRef = ref(storage, 'images/' + file.name); const uploadTask = uploadBytesResumable(storageRef, file, metadata); // Listen for state changes, errors, and completion of the upload. uploadTask.on('state_changed', (snapshot) => { // Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100; console.log('Upload is ' + progress + '% done'); }, (error) => { // Upload error }, () => { // Upload completed successfully } );
uploadBytesはtry {} catch {} では例外キャッチできないという話でした。
Firebase js sdkを使っています。
以下のコードはアップロード時にセキュリティルールに違反していたので失敗するとします。しかし、console.log("process1")
もconsole.log("catch")
も実行されません。なぜでしょうか。
try { const storagePath = `test.jpg` const blob = await (await fetch(canvas.toDataURL("image/jpg"))).blob() const storageRef = ref(publicStorage, storagePath) await uploadBytes(storageRef, blob) console.log("process1") } catch (e) { console.log("catch") }
FirebaseのJavaScript SDKのuploadBytes
メソッドは、例外ではなくPromiseを返す非同期関数です。そのため、try
-catch
ブロックでは例外をキャッチすることはできません。
上記のコードでは、アップロードに失敗した場合にcatch
節が実行されず、代わりに非同期関数のエラーハンドラが呼び出されることになります。そのため、エラーハンドラ内でエラーメッセージを表示するか、エラー処理を行う必要があります。
例えば、uploadBytes
の返り値であるPromiseがリジェクトされた場合にエラーハンドラが呼び出されますので、以下のように記述することでエラーメッセージを表示できます。
const storagePath = "test.jpg"; const blob = await (await fetch(canvas.toDataURL("image/jpeg"))).blob(); const storageRef = ref(publicStorage, storagePath); uploadBytes(storageRef, blob) .then(() => { console.log("process1"); }) .catch((error) => { console.log("catch", error); });
または、async
関数内でエラーハンドリングを行いたい場合は、try
-catch
ブロック内で関数を呼び出すこともできます。
const storagePath = "test.jpg"; const blob = await (await fetch(canvas.toDataURL("image/jpeg"))).blob(); const storageRef = ref(publicStorage, storagePath); try { await uploadBytes(storageRef, blob); console.log("process1"); } catch (error) { console.log("catch", error); }
迷走したけど、原因わかった。
bucketNameで存在しないバケット名を指定すると、Promiseが解決せずにawaitの後の処理も実行されないし、例外も発生しない状態になるみたい。バグっぽい挙動。
const storage = getStorage(getApp(), bucketName)