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

Vite+React上传图片至Firebase遇CORS错误及Bucket查找问题

解决Firebase Storage上传时的CORS错误

问题概述

调用uploadBytes函数时触发CORS错误,注释该函数后其他功能正常:

Access to XMLHttpRequest at [firebase storage api url] from origin 'http://localhost:5173' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

已定位到需要更新Firebase Storage Bucket的CORS策略,但执行gsutil cors set cors.json gs://<你的应用名称>.appspot.com时找不到对应的Bucket。

相关代码文件

vite.config.js

import { resolve } from 'path';
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

const root = resolve(__dirname, 'src');
const outDir = resolve(__dirname, 'dist');

// https://vitejs.dev/config/
export default defineConfig({
  root,
  plugins: [react()],
  build: {
    outDir,
    emptyOutDir: true,
    rollupOptions: {
      input: {
        main: resolve(root, "index.html"),
        login: resolve(root, 'auth', "login.html"),
      }
    }
  }
})

firebase.js

// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAnalytics } from "firebase/analytics";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
// TODO: Add SDKs for Firebase products that you want to use

// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
  apiKey: import.meta.env.VITE_PUBLIC_API_KEY,
  authDomain: import.meta.env.VITE_PUBLIC_AUTH_DOMAIN,
  projectId: import.meta.env.VITE_PUBLIC_PROJECT_ID,
  storageBucket: import.meta.env.VITE_PUBLIC_STORAGE_BUCKET,
  messagingSenderId: import.meta.env.VITE_PUBLIC_MESSAGING_SENDER_ID,
  appId: import.meta.env.VITE_PUBLIC_APP_ID,
  measurementId: import.meta.env.VITE_PUBLIC_MEASUREMENT_ID
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
//const analytics = getAnalytics(app);

export const auth = getAuth();
export const db = getFirestore(app);

// for image:
import { getStorage, ref, uploadBytes } from "firebase/storage"; // new
export const storage = getStorage(app)

create.jsx

import { auth, db } from "../utils/firebase"
import { useAuthState } from "react-firebase-hooks/auth"
import { useEffect, useState } from "react"
import { AiOutlineCloseCircle } from "react-icons/Ai";
import { addDoc, collection, serverTimestamp } from "firebase/firestore";

// I need to upload the photo
// create reference
// create post, including reference
import { getStorage, ref, uploadBytes } from "firebase/storage"; // new
import { nanoid } from 'nanoid'
import { storage } from '../utils/firebase'

export default function Create(props){
    const [post, setPost] = useState({imageSrc: undefined, title: "", description: ""})//maybe user id too?, probably fine without
    const [preview, setPreview] = useState();
    const [user,loading] = useAuthState(auth);

    useEffect(() => {
        if (!post.imageSrc) {
            setPost({...post, imageSrc: undefined})
            return
        }
        const objectUrl = URL.createObjectURL(post.imageSrc)
        setPreview(objectUrl)
        return () => URL.revokeObjectURL(objectUrl)
    }, [post.imageSrc])

    const handleFile = async (e) => {
        if (!e.target.files || e.target.files.length === 0) {
            setPost({...post, imageSrc: undefined})
            return
        }
        setPost({...post, imageSrc: e.target.files[0]})
    }

    const submitPost = async (e) => {
        e.preventDefault();
        const collectionRef = collection(db, "posts");

        // uploading image first:
        const photoID = nanoid()
        // const storage = getStorage();
        const storageRef = ref(storage, `images/${photoID}`);
        
        /////////////// PROBLEM IS HERE://///////////////////////////////////////////////////////
        uploadBytes(storageRef, post.imageSrc).then(() => {
            console.log("successful upload!")
        })// this is the problem, idk if the imageSrc is the prob....
        ////////////// END PROBLEM HERE /////////////////////////////////////////////////////////

        // creating image reference:
        
        // normal stuff:
        await addDoc(collectionRef, {
            title: post.title,
            description: post.description,
            //imageRef: storageRef, // just connect the image reference here, but trough the firebase bucket// why no imageref...
            timestamp: serverTimestamp(),
            user: user.uid,
            avatar: user.photoURL,
            username: user.displayName,
        });

        props.handleCreating() // closes this when done
    }

    return (
        <div className="mainCreate">
            <AiOutlineCloseCircle onClick={() => props.handleCreating()} className="closeIcon"/>
            <form onSubmit={submitPost}>
                <div className="imageBox">
                    {post.imageSrc ? <img className="imagePreview" src={preview}/> : <h2>No Image</h2>}
                    {!post.imageSrc && <input type="file" onChange={handleFile}/>}
                </div>
                <textarea className="title" placeholder="Title" onChange={(e) => setPost({...post, title: e.target.value})} value={post.title} />
                <p className={`lengthIndicator${post.title.length > 100 ? "Red" : ""}`}>{post.title.length}/100</p>
                <textarea className="description" placeholder="Description" onChange={(e) => setPost({...post, description: e.target.value})} value={post.description} />
                <p className={`lengthIndicator${post.description.length > 300 ? "Red" : ""}`}>{post.description.length}/300</p>
                <button className="createButton" type="submit">Create</button>
            </form>
        </div>
    )
}

解决步骤(Bucket定位及CORS配置)

  1. 确认Storage Bucket名称:
    • 打开Firebase控制台,进入「Storage」服务,顶部会显示Bucket地址(格式为gs://<project-id>.appspot.com);或者直接取firebaseConfig中的storageBucket字段值。
  2. 创建cors.json文件:
    在项目根目录创建该文件,内容如下:
    [
      {
        "origin": ["http://localhost:5173"],
        "method": ["GET", "POST", "PUT"],
        "maxAgeSeconds": 3600,
        "responseHeader": ["Content-Type", "Authorization"]
      }
    ]
    
  3. 配置gsutil:
    • 安装Google Cloud SDK,运行gcloud init登录关联账号并选择对应Firebase项目。
  4. 执行CORS设置命令:
    终端运行:
    gsutil cors set cors.json gs://<你的storageBucket值>
    
  5. 代码优化(可选):
    uploadBytes是异步操作,建议用await包裹,避免addDoc提前执行:
    // 修改submitPost中的上传逻辑
    try {
      await uploadBytes(storageRef, post.imageSrc);
      console.log("successful upload!");
      // 可在此获取下载URL并存入Firestore
      // const downloadURL = await getDownloadURL(storageRef);
    } catch (error) {
      console.error("上传失败:", error);
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 09:55:10