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

为什么图片上传到Firebase Storage失败且应用发生崩溃?

问题根因
  • 核心错误是Firebase Cloud Storage权限配置错误:崩溃日志明确返回403 Permission denied,说明应用当前没有权限向Storage的images路径上传文件。
  • 附加代码逻辑缺陷:
    1. 点击保存按钮后立刻调用finish()关闭页面,此时图片上传是异步操作,页面销毁会导致后续回调无法正常执行,甚至触发空指针崩溃
    2. uploadImage()方法没有判断imageUri是否为null就直接调用putFile(),如果用户没选图片就提交会直接崩溃
    3. 用while (!uriTask.isSuccessful());死循环等待下载地址,属于错误写法,会阻塞主线程
    4. 上传失败的onFailureListener是空实现,没有错误捕获逻辑,异常直接抛出导致崩溃
修复步骤

第一步:修复Firebase Storage权限

打开Firebase控制台,进入对应项目 -> 存储 -> 规则,默认规则禁止未认证用户读写,如果你还未接入用户认证,可以先临时改为测试规则(注意生产环境要替换为符合业务的权限控制,建议结合Firebase Auth做身份校验后再开放对应路径读写权限,避免数据泄露):

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if true;
    }
  }
}

发布规则后等待2分钟生效即可。

第二步:修复代码逻辑缺陷

1. 调整保存按钮逻辑,不要立刻关闭页面

修改onOptionsItemSelected中的保存逻辑,移除立刻调用的finish(),改为在所有数据写入成功后再关闭页面:

public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == R.id.action_save) {
        insertPerson();
        // 移除此处的finish(),改到sendList成功回调后执行
        return true;
    } 
    // 其余原有代码保持不变
}

2. 增加imageUri非空判断

修改insertPerson方法,新增图片选择校验:

private void insertPerson() {
    // 原有字段校验逻辑保持不变
    // 新增图片校验
    if (imageUri == null) {
        Toast.makeText(this, "请先选择人员照片", Toast.LENGTH_SHORT).show();
        return;
    }
    uploadImage();
}

3. 修复下载地址获取逻辑,替换死循环写法

private void uploadImage() {
    long timestamp = System.currentTimeMillis();
    String filePathAndName = "images/" + timestamp;
    StorageReference storageReference = FirebaseStorage.getInstance().getReference(filePathAndName);
    storageReference.putFile(imageUri)
            .addOnSuccessListener(taskSnapshot -> {
                // 替换死循环,用异步回调获取下载地址
                taskSnapshot.getStorage().getDownloadUrl().addOnSuccessListener(uri -> {
                    String uploadedImageUri = uri.toString();
                    sendList(uploadedImageUri, timestamp);
                }).addOnFailureListener(e -> {
                    Toast.makeText(AddPerson.this, "获取图片地址失败:" + e.getMessage(), Toast.LENGTH_SHORT).show();
                });
            }).addOnFailureListener(e -> {
                // 新增错误提示
                Toast.makeText(AddPerson.this, "图片上传失败:" + e.getMessage(), Toast.LENGTH_SHORT).show();
            });
}

4. 数据库写入成功后再关闭页面

修改sendList方法,增加写入结果监听:

private void sendList(String uploadedImageUri, long timestamp) {
    DatabaseReference reference = FirebaseDatabase.getInstance().getReference("List");
    HashMap<String, Object> hashMap = new HashMap<>();
    hashMap.put("firstName", firstNameString);
    hashMap.put("lastName", lastNameString);
    hashMap.put("age", ageString);
    hashMap.put("description", descriptionString);
    hashMap.put("url", uploadedImageUri);
    hashMap.put("timestamp", timestamp);
    reference.push().setValue(hashMap)
            .addOnSuccessListener(aVoid -> {
                Toast.makeText(AddPerson.this, "保存成功", Toast.LENGTH_SHORT).show();
                finish();
            })
            .addOnFailureListener(e -> {
                Toast.makeText(AddPerson.this, "数据保存失败:" + e.getMessage(), Toast.LENGTH_SHORT).show();
            });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 03:27:03