You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中如何下载Firebase Storage整个文件夹内容?

Firebase Storage 文件夹完整下载方案(Unity Android)

由于Firebase Storage没有提供直接下载整个文件夹的API,我们需要先列出目标文件夹下的所有文件,再逐个下载。以下是适配你现有代码的完整实现:

核心实现步骤

  • 获取目标文件夹的Storage引用
  • 调用ListAsync()获取文件夹内的所有文件条目
  • 提前创建本地存储目录(避免下载时路径不存在)
  • 遍历所有文件引用,逐个执行下载操作
  • 统一处理下载成功/失败的回调

完整代码示例

using System.IO;
using Firebase.Storage;
using UnityEngine;
using UnityEngine.Android;

public class FirebaseFolderDownloader : MonoBehaviour
{
    private FirebaseStorage storage;
    private StorageReference storageReference;

    // 替换为你的Firebase Storage根URL和目标文件夹路径
    private const string STORAGE_ROOT_URL = "gs://houdini-ac884.appspot.com";
    private const string TARGET_FOLDER_PATH = "uploads/your-target-folder"; // 替换成你要下载的文件夹路径
    private const string LOCAL_BASE_PATH = "SparseSpatialMap";

    public void StartFolderDownload()
    {
        Debug.Log("开始尝试下载文件夹...");

        if (Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite))
        {
            InitializeStorageReference();
            ListAndDownloadFolderFiles();
        }
        else
        {
            Debug.Log("无存储写入权限,请求权限中...");
            easyar.GUIPopup.EnqueueMessage("权限不足,正在请求存储权限", 5);
            Permission.RequestUserPermission(Permission.ExternalStorageWrite);
        }
    }

    private void InitializeStorageReference()
    {
        storage = FirebaseStorage.DefaultInstance;
        storageReference = storage.GetReferenceFromUrl(STORAGE_ROOT_URL);
    }

    private void ListAndDownloadFolderFiles()
    {
        StorageReference folderRef = storageReference.Child(TARGET_FOLDER_PATH);

        // 列出文件夹下的所有文件(默认最多返回1000个,若文件更多需处理分页)
        folderRef.ListAsync().ContinueWithOnMainThread(task =>
        {
            if (task.IsFaulted || task.IsCanceled)
            {
                Debug.LogError("获取文件列表失败: " + task.Exception);
                easyar.GUIPopup.EnqueueMessage("获取文件列表失败", 5);
                return;
            }

            ListResult result = task.Result;
            if (result.Items.Count == 0)
            {
                Debug.Log("目标文件夹为空");
                easyar.GUIPopup.EnqueueMessage("文件夹为空,无需下载", 5);
                return;
            }

            // 创建本地目标目录
            string localFolderPath = Path.Combine(Application.persistentDataPath, LOCAL_BASE_PATH, TARGET_FOLDER_PATH);
            if (!Directory.Exists(localFolderPath))
            {
                Directory.CreateDirectory(localFolderPath);
                Debug.Log("创建本地目录: " + localFolderPath);
            }

            // 遍历所有文件并下载
            int downloadedCount = 0;
            int totalFiles = result.Items.Count;

            foreach (StorageReference fileRef in result.Items)
            {
                string fileName = fileRef.Name;
                string localFilePath = Path.Combine(localFolderPath, fileName);

                fileRef.GetFileAsync(localFilePath).ContinueWithOnMainThread(downloadTask =>
                {
                    downloadedCount++;

                    if (downloadTask.IsFaulted || downloadTask.IsCanceled)
                    {
                        Debug.LogError($"文件 {fileName} 下载失败: {downloadTask.Exception}");
                        easyar.GUIPopup.EnqueueMessage($"文件 {fileName} 下载失败", 3);
                    }
                    else
                    {
                        Debug.Log($"文件 {fileName} 下载完成");
                    }

                    // 所有文件下载完成后提示
                    if (downloadedCount == totalFiles)
                    {
                        Debug.Log("所有文件下载完成");
                        easyar.GUIPopup.EnqueueMessage("文件夹下载完成", 5);
                    }
                });
            }
        });
    }

    // 权限请求回调
    private void OnApplicationFocus(bool hasFocus)
    {
        if (hasFocus && Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite))
        {
            StartFolderDownload();
        }
    }
}

关键细节说明

  • 分页处理:如果目标文件夹内文件超过1000个,需要调用ListAsync()的重载版本,传入ListOptions通过PageToken获取下一页内容
  • 本地目录创建:使用Directory.CreateDirectory()确保下载路径存在,避免因路径不存在导致下载失败
  • 异步任务管理:通过计数统计所有文件的下载状态,确保所有文件完成后给出统一提示
  • 权限处理:在OnApplicationFocus中监听权限授权结果,用户授权后自动开始下载

内容的提问来源于stack exchange,提问作者EvocativeAxis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 09:15:30