Unity C#中使用REST API上传文件至Firebase Storage失败求助
问题分析与修复方案
核心问题总结
你的Firebase Storage上传失败主要源于以下几个关键错误:
- API地址错误:使用的Storage地址格式错误,bucket标识填写有误,且附带了用于下载的
alt=media参数(上传时不需要) - 请求方法错误:上传文件到Storage REST API必须用
PUT请求,而非代码里的POST - 上传内容错误:直接传递Unity的
Sprite对象无法被API识别,需要将图片转换为二进制字节流 - 缺少权限认证:上传操作需要携带Firebase Auth的
idToken作为请求头,否则会被权限拦截 - 路径逻辑问题:用
idToken作为文件路径不合理,且编码格式不符合Storage的路径规范
修复步骤与代码示例
1. 修正Storage API地址
先在Firebase控制台找到你的存储桶名称(格式通常为[项目ID].appspot.com),替换错误的bucket部分。上传的基础地址格式应为:
https://firebasestorage.googleapis.com/v0/b/[你的存储桶名称]/o?name=[文件存储路径]
比如可以将文件路径设为users/{localId}/profile.png,用用户的localId作为路径标识更合理。
2. 转换Sprite为字节流
Unity的Sprite无法直接上传,需要转换成PNG/JPG格式的二进制字节数组,示例转换方法:
private byte[] SpriteToByteArray(Sprite sprite) { Texture2D texture = sprite.texture; // 如果Sprite是裁剪后的纹理,需要先提取裁剪区域的像素 if (sprite.rect.width != texture.width || sprite.rect.height != texture.height) { Texture2D croppedTexture = new Texture2D((int)sprite.rect.width, (int)sprite.rect.height); croppedTexture.SetPixels(texture.GetPixels((int)sprite.rect.x, (int)sprite.rect.y, (int)sprite.rect.width, (int)sprite.rect.height)); croppedTexture.Apply(); return croppedTexture.EncodeToPNG(); } return texture.EncodeToPNG(); }
3. 构建正确的上传请求
使用PUT方法,添加认证头和内容类型,传递二进制数据:
修改后的完整SignUpUser方法:
private void SignUpUser(string email, string username, string password, string age_, string mobile_, string instagram_handle_, string City_Of_Residence_, string nationality_) { string userData = "{\"email\":\"" + email + "\",\"password\":\"" + password + "\",\"returnSecureToken\":true}"; RestClient.Post<SignResponse>("https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=" + AuthKey, userData) .Then(response => { idToken = response.idToken; localId = response.localId; playerName = username; age = age_; mobile = mobile_; instagram_handle = instagram_handle_; City_Of_Residence = City_Of_Residence_; nationality = nationality_; PostToDatabase(true); // 图片上传逻辑 byte[] imageBytes = SpriteToByteArray(file2upload.sprite); string storageBucket = "你的存储桶名称.appspot.com"; // 替换为实际存储桶名称 string storageUrl = $"https://firebasestorage.googleapis.com/v0/b/{storageBucket}/o?name=users/{localId}/profile.png"; RestClient.Put(storageUrl, imageBytes) .AddHeader("Authorization", $"Bearer {idToken}") .AddHeader("Content-Type", "image/png") .Then(_ => Debug.Log("图片上传成功")) .Catch(error => Debug.Log("Image upload error: " + error.Message)); print("数据已提交"); }) .Catch(error => Debug.Log(error.Message)); }
额外注意事项
- 确保Firebase Storage的安全规则允许已认证用户上传文件,示例规则:
rules_version = '2'; service firebase.storage { match /b/{bucket}/o { match /users/{userId}/{allPaths=**} { allow write: if request.auth.uid == userId; allow read: if request.auth.uid == userId; } } } - 如果上传大尺寸图片,建议添加进度监听,避免UI假死
- 优先考虑使用Unity官方的Firebase SDK,而非直接调用REST API,SDK会自动处理文件转换、错误重试、权限校验等细节
内容的提问来源于stack exchange,提问作者Savad
相关产品推荐
相关产品推荐

