squish
squish

Reputation: 1116

How can grab my local image path, convert it it to a File object and then upload it to firebase?

I currently have a signup form. Users have an optional field where they can upload a profile picture if they want.

If they don't upload a profile picture, I want to use a default profile picture for them (imagine the default facebook profile picture image for example).

My image imported as:

import defaultPhoto from "../../assets/images/logo/grayscale-nut.png";

My register function:

const register = async () => {
    setLoading("loading");
    let newUserID;
    auth
      .createUserWithEmailAndPassword(email, confirmedPassword)
      .then((auth) => {
        if (auth) {
          newUserID = auth.user.uid;
          const collection = db.collection("users");
          collection.doc(auth.user.uid).set({
            username: username.toLowerCase().trim(),
            name: firstName,
            surname: lastName,
            bio: "",
            addressBook: [],
            medals: [],
            medalShowcase: [],
            boughtItems: [],
            soldItems: [],
          });
        }
      })
      .then(async () => {
        let photo;
        if (signUpPhoto.length === 1) {
          photo = signUpPhoto[0].file;
        } else {
          //GET THE DEFAULT PHOTO HERE
        }
        const userProfileRef = firebase
          .storage()
          .ref()
          .child(`users/` + newUserID + `/profilePicture/profilePicture`);
        userProfileRef.put(photo).then(async (snapshot) => {
          const downloadURL = await snapshot.ref.getDownloadURL();
          const userData = db.collection("users").doc(newUserID);
          userData
            .set({ profilePicture: downloadURL }, { merge: true })
            .then(async () => {
              setLoading("complete");
              const newData = await getUserByUserId(newUserID);
              setData(newData);
              history.replace("/");
            });
        });
      })
      .catch((error) => {
        setLoading("error");
      });
  };

Edit 1: The full and updated Signup page

//#####################################################################
import { useState, useEffect } from "react";
import { Link, useHistory } from "react-router-dom";
//#####################################################################
import firebase from "firebase/app";
//#####################################################################
import defaultPhoto from "../../assets/images/logo/grayscale-nut.png";
//#####################################################################
import "./Signup.scss";
import "../ui/buttons/buttons.scss";
import classNames from "classnames/bind";
import Logo from "../../assets/images/logo/seekio-logo-purple.png";
import PasswordStrengthMeter from "./components/PasswordStrengthMeter/PasswordStrengthMeter";
import PasswordMatchChecker from "./components/PasswordMatchChecker/PasswordMatchChecker";
import zxcvbn from "zxcvbn";
import ElipsisSpinner from "../ui/loading/ElipsisLoading/ElipsisSpinner";
import validator from "validator";
//#####################################################################
import { auth, db } from "../../firebase";
//#####################################################################
import { FilePond, registerPlugin } from "react-filepond";
import "filepond/dist/filepond.min.css";
import FilePondPluginFileValidateSize from "filepond-plugin-file-validate-size";
import FilePondPluginImageExifOrientation from "filepond-plugin-image-exif-orientation";
import FilePondPluginFileValidateType from "filepond-plugin-file-validate-type";
import FilePondPluginImagePreview from "filepond-plugin-image-preview";
import "filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css";
//#####################################################################
import { getUserByUserId } from "../../services/firebase";
//#####################################################################
import userDataStore from "../../Global/UserState/UserStore";
//#####################################################################
registerPlugin(
  FilePondPluginImageExifOrientation,
  FilePondPluginImagePreview,
  FilePondPluginFileValidateType,
  FilePondPluginFileValidateSize
);
function Signup() {
  //-------------------------------------------------------
  //STATES
  //-------------------------------------------------------
  const history = useHistory();
  const [email, setEmail] = useState("");
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  const [password, setPassword] = useState("");
  const [passwordStrength, setPasswordStrength] = useState(0);
  const [confirmedPassword, setConfirmedPassword] = useState("");
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  const [username, setUsername] = useState("");
  const [firstName, setFirstName] = useState("");
  const [lastName, setLastName] = useState("");
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  const [inputsFilled, setInputsFilled] = useState(false);
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  const [errorMsg, setErrorMsg] = useState(null);
  const [passwordsMatch, setPasswordsMatch] = useState(null);
  const [passwordNotStrongEnough, setPasswordNotStrongEnough] = useState(false);
  const [usernameError, setUsernameError] = useState(null);
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  const [signUpPhoto, setSignUpPhoto] = useState([]);
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  const setData = userDataStore((state) => state.setData);
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  const [loading, setLoading] = useState("idle");
  //-------------------------------------------------------
  //CLASSNAMES
  //-------------------------------------------------------
  const signUpButton = classNames({
    animateSlideUpButton: true,
    signup__buttonRegister: true,
    disabled: !inputsFilled,
  });
  //-------------------------------------------------------
  //USE EFFECTS
  //-------------------------------------------------------
  useEffect(() => {
    if (!validator.matches(username, "^[a-zA-Z0-9_.-]*$")) {
      setUsernameError("Invalid username, please try another one.");
    } else {
      setUsernameError(null);
    }
  }, [username]);
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  useEffect(() => {
    if (password !== "") {
      getPasswordScore(password);
    }
  }, [password]);
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  useEffect(() => {
    if (password !== confirmedPassword) {
      setPasswordsMatch(false);
    } else {
      setPasswordsMatch(true);
    }
  }, [password, confirmedPassword]);
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  useEffect(() => {
    if (
      (email, username, password, firstName, lastName, confirmedPassword) !== ""
    ) {
      let emailValid = emailIsValid(email);
      if (
        emailValid &&
        passwordStrength >= 2 &&
        password === confirmedPassword &&
        username.length >= 3
      ) {
        setInputsFilled(true);
      } else {
        setInputsFilled(false);
      }
    } else {
      setInputsFilled(false);
    }
  }, [
    email,
    password,
    username,
    firstName,
    lastName,
    confirmedPassword,
    signUpPhoto,
  ]);
  //-------------------------------------------------------
  //METHODS
  //-------------------------------------------------------
  async function getPasswordScore() {
    const score = zxcvbn(password).score;
    setPasswordStrength(score);
    if (score <= 2) {
      setPasswordNotStrongEnough(true);
    } else {
      setPasswordNotStrongEnough(false);
    }
  }
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  function emailIsValid(email) {
    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
  }
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  const preRegister = async (e) => {
    e.preventDefault();
    if (
      firstName.trim() === "" ||
      lastName.trim() === "" ||
      username.trim() === "" ||
      email.trim() === "" ||
      password.trim() === "" ||
      confirmedPassword.trim() === "" ||
      usernameError !== null
    ) {
      window.alert("Invalid data!\nAll data must be filled in!");
    } else {
      const usernameRef = db
        .collection("users")
        .where("username", "==", username);
      usernameRef.get().then((docs) => {
        if (docs.size === 1) {
          window.alert("Username taken");
        } else {
          register();
        }
      });
    }
  };
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  const register = async () => {
    setLoading("loading");
    let newUserID;
    auth
      .createUserWithEmailAndPassword(email, confirmedPassword)
      .then((auth) => {
        if (auth) {
          newUserID = auth.user.uid;
          const collection = db.collection("users");
          collection.doc(auth.user.uid).set({
            username: username.toLowerCase().trim(),
            name: firstName,
            surname: lastName,
            bio: "",
            addressBook: [],
            medals: [],
            medalShowcase: [],
            boughtItems: [],
            soldItems: [],
          });
        }
      })
      .then(async () => {
        const userProfileRef = firebase
          .storage()
          .ref()
          .child(`users/` + newUserID + `/profilePicture/profilePicture`);
        const userData = db.collection("users").doc(newUserID);
        if (signUpPhoto.length === 1) {
          console.log("profile picture selected");
          const photo = signUpPhoto[0].file;
          userProfileRef.put(photo).then(async (snapshot) => {
            const downloadURL = await snapshot.ref.getDownloadURL();
            userData
              .set({ profilePicture: downloadURL }, { merge: true })
              .then(async () => {
                setLoading("complete");
                const newData = await getUserByUserId(newUserID);
                setData(newData);
                history.replace("/");
              });
          });
        } else {
          console.log(
            "no profile picture  was selected, uploading the default photo instead"
          );
          userProfileRef
            .putString(defaultPhoto.toString(64).split(",")[1], "base64", {
              contentType: "image/png",
            })
            .then((s) => {
              //This console log never happens
              console.log(s);
            })
            .catch((e) => console.log(e));
        }
      })
      .catch((error) => {
        setLoading(error);
      });
  };
  //Filepond
  function onDrop(uploadedPhotos) {
    setSignUpPhoto(uploadedPhotos);
  }
  //-------------------------------------------------------
  //END
  //-------------------------------------------------------
  return (
    <div className="signup">
      {loading === "loading" ? (
        <div className="signup__loading">
          <ElipsisSpinner />
          <h4>Creating Account</h4>
        </div>
      ) : loading === "complete" ? (
        <div className="signup__loading">
          <h4>Success!</h4>
        </div>
      ) : loading === "error" ? (
        <div className="signup__loading">
          <h4>Error! Please try again.</h4>
        </div>
      ) : (
        <div className="signup__container">
          <Link to="/">
            <img src={Logo} alt="logo" className="signup__logo" />
          </Link>
          <h2>Sign-up</h2>
          <form>
            <h5>E-mail</h5>
            <input
              type="email"
              value={email}
              onChange={(e) => setEmail(e.target.value)}
              required
              className="inputText"
              placeholder="[email protected]"
            />
            <h5> Username </h5>{" "}
            <input
              type="text"
              value={username}
              onChange={(e) => setUsername(e.target.value)}
              required
              className="inputText"
              placeholder="PokeTrainer"
            />
            {usernameError && (
              <span className="errorSpan">
                <h4 className="">{usernameError}</h4>
              </span>
            )}
            <h5> Name </h5>{" "}
            <input
              type="text"
              value={firstName}
              onChange={(e) => setFirstName(e.target.value)}
              required
              className="inputText"
              placeholder="Ash"
            />
            <h5> Surname </h5>{" "}
            <input
              type="text"
              value={lastName}
              onChange={(e) => setLastName(e.target.value)}
              required
              className="inputText"
              placeholder="Ketchum"
            />
            <h5>Password</h5>
            <input
              type="password"
              value={password}
              onChange={(e) => {
                setPassword(e.target.value);
              }}
              required
              className="inputText"
              placeholder="&#9679;&#9679;&#9679;&#9679;&#9679;&#9679;&#9679;&#9679;&#9679;&#9679;"
            />
            <PasswordStrengthMeter
              passwordStrength={passwordStrength}
              password={password}
            />
            {password.length > 0 && passwordNotStrongEnough && (
              <span className="errorSpan">
                <h4>Password score of 4 or higher is required.</h4>
              </span>
            )}
            <h5> Confirm Password </h5>
            <input
              type="password"
              value={confirmedPassword}
              onChange={(e) => setConfirmedPassword(e.target.value)}
              required
              className="inputText"
              placeholder="&#9679;&#9679;&#9679;&#9679;&#9679;&#9679;&#9679;&#9679;&#9679;&#9679;"
            />
            <PasswordMatchChecker
              password={password}
              confirmPassword={confirmedPassword}
            />
          </form>
          {!passwordsMatch && (
            <span className="errorSpan">
              <h4>Passwords must match!</h4>
            </span>
          )}
          <div className="signup__container__filePondWrapper">
            <h4>Choose a profile picture:</h4>
            <div className="signup__container__filePondWrapper__wrapper">
              <FilePond
                files={signUpPhoto}
                onupdatefiles={onDrop}
                allowMultiple={false}
                maxFiles={1}
                instantUpload={false}
                name="files"
                itemInsertLocation={"after"}
                maxFileSize={"50MB"}
                acceptedFileTypes={["image/*"]}
                labelIdle={"<span class='filepond--label-action'>Browse</span>"}
                credits={null}
                stylePanelLayout={"compact circle"}
                allowImagePreview={true}
                imageCropAspectRatio={"1:1"}
                imageResizeTargetWidth={"200"}
                imageResizeTargetHeight={"200"}
              />
            </div>
          </div>
          <button type="submit" className={signUpButton} onClick={preRegister}>
            Sign Up
          </button>
          {errorMsg && <h4 className="errorMsg">{errorMsg}</h4>}
          <p>
            Our alpha is currently UK only, by signing-up you acknowledge this
            and agree to Seekio's Conditions of Use & Sale. Please see our
            Privacy Notice, our Cookies Notice and our Interest-Based Ads
            Notice.
          </p>
          <Link to="/login">
            <button className="signup__buttonSignIn">
              Already Have an Account ? Sign In
            </button>
          </Link>
        </div>
      )}
    </div>
  );
}

export default Signup;

Upvotes: 1

Views: 1006

Answers (1)

Dharmaraj
Dharmaraj

Reputation: 50930

Using base64 string and uploading worked out for me:

import image from "../path/to/image.png"

const base64String = ""

storage.ref("imageName.png")
  .putString(base64String, "base64",  {contentType: "image/png"})
  .then((s) => {
    console.log(s);
  }).catch(e => console.log(e));

Make sure you have the extension name in the file name and contentType set to correct mimetype.

Your function is async so try to use await as shown:

const register = async () => {
  setLoading("loading");
  const userCred = await auth.createUserWithEmailAndPassword(
    email,
    confirmedPassword
  );
  const newUserID = userCred.user.uid;

  const collection = db.collection("users");
  await collection.doc(auth.user.uid).set({
    username: username.toLowerCase().trim(),
    name: firstName,
    surname: lastName,
    bio: "",
    addressBook: [],
    medals: [],
    medalShowcase: [],
    boughtItems: [],
    soldItems: [],
  });

  const userProfileRef = firebase
    .storage()
    .ref()
    .child(`users/` + newUserID + `/profilePicture/profilePicture`);

  let photo;
  if (signUpPhoto.length === 1) {
    photo = signUpPhoto[0].file;
    await userProfileRef.put(photo);
  } else {
    //GET THE DEFAULT PHOTO HERE
    await userProfileRef.putString(base64String, "base64", {
      contentType: "image/png",
    });
  }

  const downloadURL = await userProfileRef.getDownloadURL();
  const userData = db.collection("users").doc(newUserID);
  await userData.set({ profilePicture: downloadURL }, { merge: true });
  setLoading("complete");
  const newData = await getUserByUserId(newUserID);
  setData(newData);
  history.replace("/");
};

Upvotes: 1

Related Questions