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

Next.js上传图片至Firebase Storage失败问题求助

问题:Next.js 上传 Firebase Storage 触发 412 Precondition Failed 错误

尝试从 Next.js 应用向 Firebase Storage 上传图片,已配置环境变量且 Firebase 初始化代码无误,Storage 规则已关闭身份验证检查,但上传时触发错误:

Error uploading image-filename.jpg
Firebase Storage: An unknown error occurred, please check the error payload for server response. (storage/unknown)

浏览器控制台显示无效请求返回 412 错误:

https://firebasestorage.googleapis.com/v0/b/firebase-storage-bucket/o?name=images%image-filename.jpg 412 (Precondition Failed)

相关代码及配置如下:

Firebase 初始化代码

// Import the functions you need from the SDKs you need
import { initializeApp, getApps } from "firebase/app";
import { getAnalytics } from "firebase/analytics";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
import { getStorage } from "firebase/storage";

// Your web app's Firebase configuration
const firebaseConfig = {
  apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
  authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
  projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
  storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
  measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
};

// Initialize Firebase
let firebaseApp;
if (!getApps().length) {
  firebaseApp = initializeApp(firebaseConfig);
}

// Initialize Firebase services
const auth = getAuth(firebaseApp);
const db = getFirestore(firebaseApp);

const STORAGE_FOLDER_PATH = `gs://${process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET}`;
const storage = getStorage(firebaseApp, STORAGE_FOLDER_PATH);

// Initialize Analytics and get analytics instance
let analytics;
if (typeof window !== "undefined") {
  analytics = getAnalytics(firebaseApp);
}

export { firebaseApp, auth, db, storage, analytics };

上传组件核心代码

const handleUpload = async () => {
  if (imageFiles.length === 0) {
    //handle condition if no image is selected
  }
  
  setIsUploading(true);
  const uploadPromises = imageFiles.map(async ({ file }) => {
    const filename = nanoid();
    const fileExt = file.name.split(".").pop();

    const storageRef = fireRef(
      storage,
      `images/${filename}.${fileExt}`
    );
    try{
      const res = await uploadBytes(storageRef, file);
      return res.metadata.fullPath;
    } catch (error) {
      toast.error(`Error uploading ${file.name}`, {
        description: error.message,
      });
      return null;
    }      
  });

  try {
    const uploadedUrls = await Promise.all(uploadPromises);      
    const validUrls = uploadedUrls.filter(url => url !== null);

    if (validUrls.length > 0) {
      toast.success(`Successfully uploaded ${validUrls.length} image${validUrls.length === 1 ? '' : 's'}`);        
    }
    setIsUploading(false);
    return validUrls;
  } catch (error) {
    toast.error("Error uploading images", {
      description: error.message,
    });
    setIsUploading(false);
    return [];
  }
};

Storage 规则配置

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

    match /users/{userId}/{allPaths=**} {
      allow read: if true;
      allow write: if true;
    }
  }
}

解决方案

核心原因

初始化 Storage 时错误传入了完整的 gs:// 格式路径作为存储桶 URL,导致后续生成文件引用时路径拼接异常,出现无效的请求路径(如 images%image-filename.jpg 缺少路径分隔符),触发 412 预条件失败。

修复步骤

  1. 修正 Storage 初始化代码
    移除手动拼接的 gs:// 路径,getStorage 会自动读取 firebaseConfig 中的 storageBucket 值,无需额外传入存储桶 URL:

    // 删除错误的路径定义
    // const STORAGE_FOLDER_PATH = `gs://${process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET}`;
    
    // 直接初始化 storage
    const storage = getStorage(firebaseApp);
    
  2. 验证路径拼接逻辑
    上传时的文件路径(images/${filename}.${fileExt})本身逻辑正确,修正 Storage 初始化后,会自动生成有效的相对路径,请求 URL 格式将恢复正常。

  3. 重新测试上传
    重启应用后尝试上传图片,412 错误即可解决。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 06:04:52