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

向Firebase数据库上传文件时返回空对象的问题求助

问题解决:Firebase中存储图片后显示空对象

问题场景

通过Axios将Canvas生成的图片以File对象形式发送到Firebase Realtime Database时,数据库中image字段对应的是空对象,但生成的File对象本身包含正确的文件名、大小、类型等信息。

用户原始代码:

var dataCanvas = canvas.toDataURL().replace("data:image/png;base64,", "");

let file;
let config = {
  headers: {
    "Content-Type": "multipart/form-data",
  },
};

const linkSource = `data:image/png;base64,${dataCanvas}`;
await fetch(linkSource)
  .then((res) => res.blob())
  .then((blob) => {
    file = new File([blob], "test", {
      type: "image/png"
    });

    console.log('file is founded', file);
    axios.post(
        "https://DB.firebaseio.com/screens.json",
        JSON.stringify({
          image: JSON.stringify(file)
        }),
        config

      )
      .then(function(response) {
        console.log('response    ', response);
      })
      .catch(function(error) {
        // console.log(error);
      });
  });

核心原因

  1. File对象无法被JSON序列化:JSON.stringify(file)仅能序列化对象的可枚举属性,而File/Blob的核心二进制数据不属于可枚举属性,序列化后仅保留空壳结构,最终存入Firebase的就是空对象。
  2. Realtime Database不支持二进制存储:Firebase Realtime Database是JSON文档型数据库,仅适合存储字符串、数字、数组、JSON对象这类结构化数据,无法直接存储二进制文件。

解决方案

方案1:用Firebase Storage存图片,Realtime Database存访问链接(推荐)

这是Firebase官方推荐的文件存储方案,将二进制文件存在专门的Storage服务中,数据库仅保存文件的下载链接,既节省数据库空间,又方便后续访问。

代码示例(使用Firebase SDK)

// 假设已完成Firebase App初始化
const storage = firebase.storage();
const storageRef = storage.ref('screens/test.png'); // 指定存储路径和文件名

var dataCanvas = canvas.toDataURL().replace("data:image/png;base64,", "");
const linkSource = `data:image/png;base64,${dataCanvas}`;

await fetch(linkSource)
  .then(res => res.blob())
  .then(blob => storageRef.put(blob)) // 上传Blob到Storage
  .then(snapshot => snapshot.ref.getDownloadURL()) // 获取下载链接
  .then(downloadURL => {
    // 将链接存入Realtime Database
    return axios.post(
      "https://DB.firebaseio.com/screens.json",
      { image: downloadURL }
    );
  })
  .then(response => console.log('操作成功', response))
  .catch(error => console.error('操作失败', error));

代码示例(使用Axios调用REST API)

如果不想引入Firebase SDK,可直接调用Storage的REST接口:

var dataCanvas = canvas.toDataURL().replace("data:image/png;base64,", "");
const linkSource = `data:image/png;base64,${dataCanvas}`;

await fetch(linkSource)
  .then(res => res.blob())
  .then(blob => {
    const formData = new FormData();
    formData.append('file', blob, 'test.png');
    
    // 替换为你的Storage Bucket地址,格式:https://firebasestorage.googleapis.com/v0/b/[你的Bucket名]/o/[存储路径]
    const storageUrl = "https://firebasestorage.googleapis.com/v0/b/your-bucket-name/o/screens%2Ftest.png";
    
    // 上传到Storage
    return axios.post(storageUrl, formData, { params: { uploadType: 'media' } });
  })
  .then(storageRes => {
    // 拼接下载链接
    const downloadURL = `https://firebasestorage.googleapis.com/v0/b/your-bucket-name/o/${storageRes.data.name}?alt=media`;
    // 存入Realtime Database
    return axios.post("https://DB.firebaseio.com/screens.json", { image: downloadURL });
  })
  .then(dbRes => console.log('完成', dbRes))
  .catch(err => console.error('出错', err));

方案2:直接存储Base64字符串(不推荐)

如果仅需临时存储小体积图片,可跳过File/Blob转换,直接将Canvas生成的Base64字符串存入数据库:

var dataCanvas = canvas.toDataURL().replace("data:image/png;base64,", "");

axios.post(
  "https://DB.firebaseio.com/screens.json",
  { image: dataCanvas }
)
.then(response => console.log('保存成功', response))
.catch(error => console.error('保存失败', error));

注意:Base64字符串体积比原二进制文件大30%左右,大量存储会占用过多数据库空间,仅适合小图场景。

额外注意

  • 确保Firebase Storage的安全规则允许上传和访问(开发阶段可临时设置为公开,生产环境需配置严格的权限规则)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 12:40:25