Unity中实现批量上传文件夹文件至Firebase Storage
批量上传SparseSpatialMap目录文件到Firebase Storage(Unity/C#)
你可以通过遍历目标目录下的所有文件,复用现有上传逻辑实现批量上传。以下是修改后的完整代码及关键说明:
using System.IO; using System.Threading.Tasks; using UnityEngine; using Firebase.Storage; public class FirebaseBatchUpload : MonoBehaviour { FirebaseStorage storage; StorageReference storageReference; void Start() { UploadAllFilesInSparseSpatialMap(); } void UploadAllFilesInSparseSpatialMap() { if (Permission.HasUserAuthorizedPermission(Permission.ExternalStorageRead)) { Debug.Log("权限已获取"); // 拼接目标目录完整路径 string targetDirectory = Path.Combine(Application.persistentDataPath, "SparseSpatialMap"); // 检查目录是否存在 if (!Directory.Exists(targetDirectory)) { Debug.LogError($"目录不存在:{targetDirectory}"); return; } // 获取目录下所有文件(仅当前目录,如需包含子目录改为SearchOption.AllDirectories) string[] allFiles = Directory.GetFiles(targetDirectory, "*", SearchOption.TopDirectoryOnly); if (allFiles.Length == 0) { Debug.Log("目录下无文件"); return; } // 初始化Firebase Storage引用 storage = FirebaseStorage.DefaultInstance; storageReference = storage.GetReferenceFromUrl("gs://houdini-ac884.appspot.com"); // 批量发起上传任务 var uploadTasks = new Task<StorageMetadata>[allFiles.Length]; for (int i = 0; i < allFiles.Length; i++) { uploadTasks[i] = UploadSingleFile(allFiles[i]); } // 等待所有上传任务完成 Task.WhenAll(uploadTasks).ContinueWith(task => { if (task.IsFaulted) { Debug.LogError("部分文件上传失败:" + task.Exception.ToString()); } else { Debug.Log("所有文件上传完成"); } }); } else { Debug.Log("未获取权限,请求权限中"); Permission.RequestUserPermission(Permission.ExternalStorageRead); } } /// <summary> /// 复用的单文件上传方法 /// </summary> Task<StorageMetadata> UploadSingleFile(string localFilePath) { // 提取文件名,作为Firebase存储路径的一部分 string fileName = Path.GetFileName(localFilePath); StorageReference fileRef = storageReference.Child($"uploads/{fileName}"); // 用二进制流读取文件,适配所有文件类型 using (FileStream stream = File.OpenRead(localFilePath)) { return fileRef.PutStreamAsync(stream).ContinueWith(task => { if (task.IsFaulted || task.IsCanceled) { Debug.LogError($"上传失败 {localFilePath}:{task.Exception.ToString()}"); throw task.Exception; } else { StorageMetadata metadata = task.Result; Debug.Log($"上传完成:{fileName} | MD5哈希:{metadata.Md5Hash}"); return metadata; } }); } } }
关键改动说明
- 目录遍历:通过
Directory.GetFiles获取目标目录下所有文件,可通过SearchOption参数控制是否包含子目录。 - 文件流优化:改用
File.OpenRead获取二进制流,避免StreamReader仅适配文本文件的局限,兼容所有文件类型。 - 批量任务管理:用
Task.WhenAll统一等待全部上传任务完成,方便批量处理结果。 - 动态存储路径:保留原文件名作为Firebase存储路径的一部分,避免文件名冲突。
- 错误防护:新增目录存在性、空文件检查,单个文件上传失败时单独记录日志,不影响其他文件上传。
可选扩展
如果需要保留原目录结构(比如子目录文件上传到Firebase对应路径),可以计算文件相对路径替换fileName:
// 计算文件相对于目标目录的路径 string relativePath = Path.GetRelativePath(targetDirectory, localFilePath); // 替换路径分隔符为Firebase兼容的斜杠 relativePath = relativePath.Replace('\\', '/'); StorageReference fileRef = storageReference.Child($"uploads/{relativePath}");
内容的提问来源于stack exchange,提问作者EvocativeAxis
相关产品推荐
相关产品推荐

