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

如何在Firebase本地模拟器中上传图片至Web端?

问题描述

尝试在Firebase本地模拟器中将图片上传至Storage存储桶时,遇到错误:

Unhandled error FirebaseError: Firebase: Need to provide options, when not being deployed to hosting via source. (app/no-options). at initializeApp

尝试使用Admin SDK初始化代码:

const defaultApp = initializeApp({ credential: applicationDefault() })

但调用const storage = getStorage()仍报相同授权错误;改用defaultApp.storage()能获取到对象,但该对象属于Admin SDK的Bucket类型,无法使用Web客户端SDK的ref、uploadBytesResumable等方法。完整代码如下:

import cuid from "cuid";
import {
  getStorage,
  ref,
  uploadBytes,
  uploadBytesResumable,
  getDownloadURL
} from "firebase/storage";
import { admin, defaultApp } from '../utils/firebaseInit'

export function saveToBucket(url: string): string {
  const normalStorage = getStorage() // Gets a FirebaseStorage instance for the given Firebase app. but NOT AUTHED
  const defaultStorage = defaultApp.storage(); // Gets the default FirebaseStorage instance.
  const storageRef = ref(normalStorage)
  const bucketPath = `personas-out/img-${cuid()}.jpg`

  const bucket = defaultStorage.bucket();
  // const bucketRef = bucket.ref(); // Property 'ref' does not exist on type 'Bucket'.ts(2339)

  const metadata = {
    contentType: 'image/jpeg'
  };

  const imageRef = ref(storageRef, bucketPath);
  const file = new File([url], bucketPath, {
    type: "image/jpeg",
  });
  // will happen in the background?
  uploadBytesResumable(imageRef, file, metadata)
    .then((snapshot: any) => {
      console.log('Uploaded', snapshot);
    });

  return bucketPath
}
解决方案

核心问题是混淆了Firebase Admin SDK和Web客户端SDK的用法,两者分属不同运行环境,API风格完全独立,不能混用:

1. 明确SDK使用场景

  • Admin SDK:用于服务端(Node.js/后端),拥有全权限,通过bucket()接口操作存储桶。
  • Web客户端SDK:用于前端浏览器环境,需初始化时配置存储桶信息,使用getStorage、ref、uploadBytesResumable等专属方法。

2. 服务端(Node.js)使用Admin SDK连接模拟器

若代码运行在服务端,按以下方式配置:

import { initializeApp, applicationDefault } from 'firebase-admin/app';
import { getStorage } from 'firebase-admin/storage';
import cuid from "cuid";
import fs from 'fs';

// 初始化Admin App并配置存储桶
const app = initializeApp({
  credential: applicationDefault(),
  storageBucket: 'your-bucket-name.appspot.com' // 替换为你的存储桶名称
});

// 连接Storage模拟器
const storage = getStorage(app);
storage.bucket().setStorageEmulator('localhost', 9199); // 模拟器默认端口9199

export async function saveToBucket(filePath: string): Promise<string> {
  const bucketPath = `personas-out/img-${cuid()}.jpg`;
  const bucket = storage.bucket();
  
  // 上传本地文件(若为网络文件需先下载为流)
  await bucket.upload(filePath, {
    destination: bucketPath,
    metadata: { contentType: 'image/jpeg' }
  });

  return bucketPath;
}

3. 前端使用Web客户端SDK连接模拟器

若代码运行在浏览器环境,按以下方式配置:

import { initializeApp } from "firebase/app";
import { getStorage, ref, uploadBytesResumable, connectStorageEmulator } from "firebase/storage";
import cuid from "cuid";

// 从Firebase控制台获取你的项目配置
const firebaseConfig = {
  apiKey: "YOUR_API_KEY",
  authDomain: "YOUR_AUTH_DOMAIN",
  projectId: "YOUR_PROJECT_ID",
  storageBucket: "YOUR_BUCKET_NAME.appspot.com", // 必填项
  messagingSenderId: "YOUR_SENDER_ID",
  appId: "YOUR_APP_ID"
};

const app = initializeApp(firebaseConfig);
const storage = getStorage(app);

// 连接Storage模拟器
connectStorageEmulator(storage, "localhost", 9199);

export function saveToBucket(file: File): string {
  const bucketPath = `personas-out/img-${cuid()}.jpg`;
  const imageRef = ref(storage, bucketPath);
  
  uploadBytesResumable(imageRef, file, { contentType: 'image/jpeg' })
    .then(snapshot => {
      console.log('上传完成', snapshot);
    });

  return bucketPath;
}

关键注意事项

  • 禁止混用两类SDK的API:比如用Admin初始化的App调用Web客户端的getStorage,或用Web客户端App调用Admin的bucket()。
  • 运行代码前需确保Storage模拟器已启动:执行firebase emulators:start --only storage。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 04:45:58