Why am I not getting firebase storage files url in my react app?

Viewed 511

In my React app, I've main three functionality which is connected to firebase. firebase auth, real-time chat, and this third one require firebase storage. I want to upload images with chat messages. when I try to upload images, the console gives me this error when I try to console.log(url)
I want to get that downloaded image url and store it in my firestore database and then use that url inside my Message.js component. console shows me this error


My Chat.js component

  const [messages, setMessages] = useState([]);
  const [assets, setAssets] = useState(null);

  useEffect(() => {
    if (channelId) {
      db.collection("channels")
        .doc(channelId)
        .collection("messages")
        .orderBy("timestamp", "desc")
        .onSnapshot((snapshot) => {
          setMessages(snapshot.docs.map((doc) => doc.data()));
        });
    }
  }, [channelId]);

  const sendMessage = (e) => {
    e.preventDefault();
    const uploadTask = storage.ref(`assets_discord/${assets.name}`).put(assets);
    uploadTask.on("state_changed", () => { 
      storage
        .ref("assetsdiscord")
        .child(assets.name)
        .getDownloadURL()
        .then((url) => {
          db.collection("assetUrl").add({
            imgUrl: url,
          });
          console.log(url);
          setAssets(null);
        });
      });
      db.collection("channels").doc(channelId).collection("messages").add({
        user: user,
        message: input,
        timestamp: firebase.firestore.FieldValue.serverTimestamp(),
      });
      
    setInput("");
  };

  const hideInput = (e) => {
    e.preventDefault();
    setShowInput(!showInput);
  };

  return (
    <div className="chat">
      {channelId ? (
        <>
          <ChatHeader channelName={channelName} />
          <div className="chat__messages">
            {messages.map((message) => (
              <Message
                user={message.user}
                message={message.message}
                timestamp={message.timestamp}
                assetUrl={message.imgUrl}
              />
            ))}
          </div>
          <div className="chat__input">
            {showInput ? (
              <>
                <form action="#">
                  <label htmlFor="imgFiles" className="upload__img">
                    <AddCircle fontSize="large" />
                  </label>
                  <input
                    type="file"
                    id="imgFiles"
                    className="hidden"
                    accept="image/*"
                    onChange={(e) => {
                      if (e.target.files[0]) {
                        setAssets(e.target.files[0]);
                      }
                    }}
                  />
                  <input
                    disabled={!channelId}
                    value={input}
                    onChange={(e) => setInput(e.target.value)}
                    type="text"
                    placeholder={`Send Message to #${channelName}`}
                  />
                  <button
                    onClick={sendMessage}
                    className="chat__inputButton"
                    type="Submit"
                  >
                    Send Message
                  </button>
                  <button onClick={hideInput}>Hide</button>
                </form>
              </>
            ) : (
              <p
                onClick={() => setShowInput(!showInput)}
                className="show__input"
              >
                Show
              </p>
            )}
          </div>
        </>
      ) : (
        <>
          <div className="chat__selectRoom">
            <ArrowLeftIcon
              style={{ fontSize: "30px" }}
              className="arrow__left"
            />
            <h3>Select Any Room to get Started</h3>
          </div>
        </>
      )}
    </div>
  );

Message Component

const Message = ({ user, timestamp, message, assetUrl }) => {
  // console.log(assetUrl);
  return (
    <div className="message">
      <Avatar src={user.photo} />
      <div className="message__info">
        <h4>
          {user.displayName}
          <span className="message__timestamp">
            {new Date(timestamp?.toDate()).toUTCString()}
          </span>
        </h4>
        <p>{message}</p>
        {/*
         <ImageUpload assetUrl={assetUrl} /> 
       */}
        <img src={assetUrl} alt="dummy" />
      </div>
    </div>
  );
};

firebase sequrity rules

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write;
    }
  }
}
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if true;
    }
  }
}

Link to live website

2 Answers

Go to the firebase console then select the project you are working on then go to storage then rules.

enter image description here

If you are using firestore or database then check the rules. Another problem can be that you have not added the SHA of your project. We are allowing everyone to change the storage means public access.

In your case, as you commented, the problem can be security access. Here is a link to google documenations

I would suggest you read documentation before using any platforms like Amazon AWS, firebase, or any type of API.

Another CHeck - Check the address of the files, I rechecked the error. Your security rules are correct, I think you should use some samples from documentations.

When you are referring to upload you are using 'assets_discord' but when you want to get the URL you are referring to 'assetsdiscord'

Related