☁️

[Unity]Firebase CloudStorageにて実機からファイルをアップロードする

2021/09/14に公開

背景

ドキュメントの方法でファイルをFirebase CloudStorageにアップロードしようとすると、Unityエディターからはアップデートできるが実機でエラーが出て失敗する。

エラー

CFURLResourceIsReachable failed because it was passed an URL which has no scheme
Firebase.Storage.StorageException: No object exists at the desired reference

対応

エラー文に書いてありますが、原因は指定した引数にschemeが付いてないからですね。

元々のコードはこんな感じでした。

public void UploadImageAsync(string localFilePath,int userId,Action<string> onComplete)
{
    // localFilePathはApplication.persistentDataPath + file名
    var fileName = $"xxxxxxx";
    var imageRef = StorageRef.Child($"{fileName}.png");
    var metadataChange = new MetadataChange {ContentType = "image/png"};
    imageRef.PutFileAsync(localFilePath,metadataChange).ContinueWith(task =>
    {
	if (task.IsFaulted || task.IsCanceled)
	{
	    STDebug.Log(task.Exception.ToString());
	    onComplete.Call(null);
	}
	else
	{
	    onComplete.Call(fileName);
	}
    });
}

ここでlocalFilePathにはApplication.persistentDataPathとfile名を結合したものが入っていました。
UnityEditor上だとこれでちゃんとアップロード完了します。

実機でもちゃんとアップロードできるようにするには、

file://

をパスの前につける必要があります。

private static string UriFileScheme = Uri.UriSchemeFile + "://";
protected virtual string GetFileUri(string filepath) {
    if (filepath.StartsWith(UriFileScheme)) {
	return filepath;
    }
    return String.Format("{0}{1}", UriFileScheme, filepath);
}
public void UploadImageAsync(string localFilePath,int userId,Action<string> onComplete)
{
    var fileName = $"xxxxxxx";
    var imageRef = StorageRef.Child($"{fileName}.png");
    var metadataChange = new MetadataChange {ContentType = "image/png"};
    // FilePathではなくUriを指定するようにする
    var localFileUri = GetFileUri(localFilePath);
    imageRef.PutFileAsync(localFilePath,metadataChange).ContinueWith(task =>
    {
	if (task.IsFaulted || task.IsCanceled)
	{
	    STDebug.Log(task.Exception.ToString());
	    onComplete.Call(null);
	}
	else
	{
	    onComplete.Call(fileName);
	}
    });
}

こんな感じで指定すれば動くようになりました。
Editor上では動くもんだから原因の特定に1時間くらいかかってしまった...。

参考:
https://github.com/firebase/quickstart-unity/issues/396#issuecomment-505642527

余談

自分のアプリでいうと
大喜利オンラインの画像投稿機能
定時退社オンラインの引き継ぎ機能
でこれを使おうと思っていたので助かりました。

Discussion