Как использовать Firebase для загрузки изображений в Next.js?

Я просматриваю видеоурок о Nextjs и вижу, что версия Firebase, которую он использует, устарела. Мне удалось выполнить все шаги, прочитав документацию, пока я не дошел до этого момента.

Искал здесь и нашел несколько интересных ответов о том, как добиться возможности загрузки изображений в Firebase. Вот ссылка

Перепробовали все решения, и ни одно из них не сработало. Я получаю сообщение об ошибке:


FirebaseError: Firebase Storage: An unknown error occurred, please check the error payload for server response. (storage/unknown)
Bad Request

Вот код, который я пытаюсь:

import Image from "next/image";
import { useSession } from "next-auth/react";
import { FaceSmileIcon } from "@heroicons/react/24/outline";
import { VideoCameraIcon, PhotoIcon } from "@heroicons/react/20/solid";
import { useRef } from "react";
import { db, storage } from "../firebase";
import { collection, addDoc, serverTimestamp, doc, setDoc } from "firebase/firestore";
import { useState } from "react";
import {ref, uploadString, getDownloadURL, getStorage} from "firebase/storage";

function InputBox() {

    const {data: session} = useSession();
    const inputRef = useRef(null);
    const filePickerRef = useRef(null);
    const [imageToPost, setImageToPost] = useState(null);

    const sendPost = async (e) => {
        e.preventDefault();
        if (!inputRef.current.value) return;

        const colRef = collection(db, "posts")

        await addDoc(colRef, {
            message: inputRef.current.value,
            name: session.user.name,
            email: session.user.email,
            image: session.user.image,
            timestamp: serverTimestamp(),
        }).then((document) => {
            if (imageToPost) {
                const storageRef = ref(storage, `posts/${document.id}`);
                uploadString(storageRef, imageToPost, "data_url").then((snapshot) => {
                    getDownloadURL(snapshot.ref).then(URL => {
                        setDoc(doc(db, "posts", document.id), 
                        {imageToPost: URL}, {merge: true}
                        );
                    });
                })
                removeImage();
            }
        })
        inputRef.current.value = "";
    };

    const addImageToPost = (e) => {
        const reader = new FileReader();
        if (e.target.files[0]) {
            reader.readAsDataURL(e.target.files[0]);
        }

        reader.onload = (readerEvent) => {
            setImageToPost(readerEvent.target.result);
        }
    };

    const removeImage = () => {
        setImageToPost(null);
    };

    return ( <HERE THE REST OF THE CODE>

Не сердись на меня. Я действительно пытался сделать все возможное, чтобы найти решение и не публиковать здесь.

Любая помощь будет очень признательна, потому что я не могу понять, что не так, потому что, как упоминалось ранее, я пробовал все варианты, которые нашел до сих пор.

BTW также пытался назначить хранилище для getStorage() до const storageRef = ref(storage, `posts/${document.id}`);

Вот так:

.then((document) => {
   if (imageToPost) {
      const storage = getStorage();
      const storageRef = ref(storage, `posts/${document.id}`);

<MORE CODE>

И мой firebase.jsфайл:

import { initializeApp } from 'firebase/app';
import { getStorage } from "firebase/storage";

const firebaseConfig = {
    apiKey: "APIKEY-HERE",
    authDomain: "AUTHDOMAIN-HERE",
    projectId: "PROJECT-ID-HERE",
    storageBucket: "STORAGE-BUCKET-HERE",
    messagingSenderId: "MESSAGING-SENDER-HERE",
    appId: "APPID-HERE"
  };


  const app = initializeApp(firebaseConfig);
  const db = getFirestore(app);

  const storage = getStorage(app);

  export { db, storage };
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
315
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Попробуй это. Я использовал firebase v8.6.3.

const docRef = firebase.firestore().collection("colection_name").doc();
const storageRef = firebase.storage().ref();
const uploadTask = storageRef.child('/posts/' + imageToPost.name).put(imageToPost);
console.info(uploadTask)
uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED, // or 'state_changed'
    (snapshot) => {
        // Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
        var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
        console.info('Upload is ' + progress + '% done');
        switch (snapshot.state) {
            case firebase.storage.TaskState.PAUSED: // or 'paused'
                console.info('Upload is paused');
                break;
            case firebase.storage.TaskState.RUNNING: // or 'running'
                console.info('Upload is running');
                break;
        }
    },
    (error) => {
        // A full list of error codes is available at
        // https://firebase.google.com/docs/storage/web/handle-errors
        switch (error.code) {
            case 'storage/unauthorized':
                // User doesn't have permission to access the object
                break;
            case 'storage/canceled':
                // User canceled the upload
                break;

            // ...

            case 'storage/unknown':
                // Unknown error occurred, inspect error.serverResponse
                break;
        }
    },
    () => {
        // Upload completed successfully, now we can get the download URL
        uploadTask.snapshot.ref.getDownloadURL().then((downloadURL) => {
            console.info('File available at', downloadURL);
            docRef.set({
                message: inputRef.current.value,
                name: session.user.name,
                email: session.user.email,
                image: downloadURL,
            });
        });
    }
);

Если вы не хотите, чтобы процесс загрузки и ошибка отображались, вы можете избавиться от этих кодов и сразу перейти к getDownloadURL.

Спасибо. Должен ли этот код заменить весь код внутри const sendPost = async (e) => {? Ценить

Zaesar 03.11.2022 16:18

Замените этот код из этой строки const colRef = collection(db, "posts") на removeImage();}})

Shiva C 03.11.2022 16:21

Измените имя коллекции и imageToPost в соответствии с вашим кодом.

Shiva C 03.11.2022 16:23

Извините, что прерываю вас, но в моем коде нет названия коллекции. А какое должно быть imageToPost.name? В моем коде нет ничего, указывающего на это. Еще раз извините, что отнял у вас время. Непонятно, что мне нужно изменить в вашем коде, чтобы он работал на моем. Я просто понимаю, что нужно взять ваш код и опубликовать его после const colRef = collection(db, "posts") до removeImage();ПРИМЕЧАНИЕ. У меня есть оператор if (if (imageToPost)), где внутри находится removeImage(), поэтому для меня это не имеет смысла... Опять же, извините, что отнимаю ваше время.

Zaesar 03.11.2022 16:32

Вы упомянули «сообщения» в качестве названия своей коллекции. Надеюсь, ты прав. Нет необходимости менять «imageToPost.name». Вызовите этот метод removeImage() после inputRef.current.value = "";

Shiva C 03.11.2022 16:38

Не следуйте слепо видеоуроку. Поймите основы. Счастливого обучения

Shiva C 03.11.2022 16:40

Спасибо за уточнение. Я понимаю основы, просто я вижу, что ваша структура кода сильно отличается от той, которую я опубликовал. Очень ценю ваши усилия, чтобы помочь мне :)

Zaesar 03.11.2022 16:48

Я получаю TypeError: firebase_app__WEBPACK_IMPORTED_MODULE_6__.firestore is not a function, указывающий на const docRef = firebase.firestore().collection("posts").doc(); Imported import * as firebase from "firebase/app";, но не могу решить эту проблему.

Zaesar 03.11.2022 16:53

Какую версию firebase вы используете?

Shiva C 03.11.2022 16:58

Если v8, то импортируйте как этот import firebase from "firebase/app" // Добавьте продукты Firebase, которые вы хотите использовать import "firebase/firestore" import "firebase/storage" Если вы используете v9, это не будет работать. Вам нужно изменить много вещей в соответствии с v9.

Shiva C 03.11.2022 17:00

Хорошо, я использую firebase версии 9.13.0. Нужно найти другой способ добиться этого.

Zaesar 03.11.2022 17:03

Логика такая же и в v9. Но вы должны импортировать метод v9 и использовать его в соответствии с ним. Вы можете сослаться на документы firebase для этого.

Shiva C 03.11.2022 17:14

Да, я читаю документы и делаю, как они говорят. Но все равно получаю эту ошибку... [stackoverflow.com/questions/70052479/… нашел и другой случай с такой же ошибкой

Zaesar 03.11.2022 17:45
Ответ принят как подходящий

Попробуйте это, это сработало для меня: Firebase: "^9.0.0"

addDoc(dbInstance, {
      message: inputRef.current.value,
      name: session?.user?.name,
      email: session?.user?.email,
      image: session?.user?.image,
      timestamp: serverTimestamp(),
    }).then((doc) => {
      if (imageToPost) {
        const storageRef = ref(storage, `posts/${doc.id}`);

        uploadString(storageRef, imageToPost, "data_url").then((snapshot) => {
          getDownloadURL(snapshot.ref).then((url) => {
            addDoc(dbInstance, { postImage: url });
          });
        });

        removeImage();
      }
    });

    inputRef.current.value = "";

Другие вопросы по теме