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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 23:01:13