首页 > 解决方案 > React Native Expo:用户选择后立即将图像加载到 firabse 存储

问题描述

在努力将图像上传到 Firebase 存储并将其保存到用户 Firebase firestore 之后,我终于成功实现了这一目标。

我是这样做的:

  const [image, setImage] = useState(null);
  const [userData, setUserData] = useState("");

  const [uploading, setUploading] = useState("");
  const getPermission = async () => {
    if (Platform.OS !== "web") {
      const { status } =
        await ImagePicker.requestMediaLibraryPermissionsAsync();
      if (status !== "granted") {
        alert("Sorry, we need camera roll permissions to make this work!");
      }
    }
  };
  const getUserData = async () => {
    await firebase
      .firestore()
      .collection("users")
      .doc(firebase.auth().currentUser.uid)
      .get()
      .then((documentSnapshot) => {
        if (documentSnapshot.exists) {
          setUserData(documentSnapshot.data());
        }
      });
  };

  const pickImage = async () => {
    let result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.All,
      allowsEditing: true,
      aspect: [4, 3],
      quality: 1,
    });
    if (!result.cancelled) {
      setImage(result.uri);
    }
  };

  const getPictureBlob = (uri) => {
    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest();
      xhr.onload = function () {
        resolve(xhr.response);
      };
      xhr.onerror = function (e) {
        reject(new TypeError("Network request failed"));
      };
      xhr.responseType = "blob";
      xhr.open("GET", image, true);
      xhr.send(null);
    });
  };

  // here I am uploading the image to firebase storage
  const uploadImageToBucket = async () => {
    let blob;
    try {
      setUploading(true);
      blob = await getPictureBlob(image);

      const ref = await storage.ref().child(uuid.v4());
      const snapshot = await ref.put(blob);
      console.log("link path");
      return await snapshot.ref.getDownloadURL();
    } catch (e) {
      alert(e.message);
    } finally {
      blob.close();
      setUploading(false);
    }
  };

  const UpdateImage = async () => {
    let imgUrl = await uploadImageToBucket();
    if (imgUrl === null && userData.photoURL) {
      imgUrl = userData.photoURL;
    }
    firebase
      .firestore()
      .collection("users")
      .doc(firebase.auth().currentUser.uid)
      .update({
        photoURL: imgUrl,
      })
      .then(() => console.log("user Upadted"));
  };

  useEffect(() => {
    getPermission();
  }, []);
  useEffect(() => {
    getUserData();
  }, []);

我的问题是用户首先选择一个图像,然后他应该按上传按钮将其上传到 Firebase 存储,最后单击更新按钮以更新 Firestore 中的图片。因为我希望用户能够在选择图像后立即将图像上传到 Firebase 存储,而无需单击上传按钮。

标签: javascriptfirebasereact-nativeexporeact-native-firebase

解决方案


你能用这段代码试试吗:

const [image, setImage] = useState(null);
const [userData, setUserData] = useState("");

const [uploading, setUploading] = useState("");
const getPermission = async () => {
  if (Platform.OS !== "web") {
    const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
    if (status !== "granted") {
      alert("Sorry, we need camera roll permissions to make this work!");
    }
  }
};
const getUserData = async () => {
  await firebase
    .firestore()
    .collection("users")
    .doc(firebase.auth().currentUser.uid)
    .get()
    .then((documentSnapshot) => {
      if (documentSnapshot.exists) {
        setUserData(documentSnapshot.data());
      }
    });
};

const pickImage = async () => {
  let result = await ImagePicker.launchImageLibraryAsync({
    mediaTypes: ImagePicker.MediaTypeOptions.All,
    allowsEditing: true,
    aspect: [4, 3],
    quality: 1,
  });
  if (!result.cancelled) {
    UpdateImage(result.uri);
  }
};

const getPictureBlob = (uri) => {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.onload = function () {
      resolve(xhr.response);
    };
    xhr.onerror = function (e) {
      reject(new TypeError("Network request failed"));
    };
    xhr.responseType = "blob";
    xhr.open("GET", image, true);
    xhr.send(null);
  });
};

// here I am uploading the image to firebase storage
const uploadImageToBucket = async (img) => {
  let blob;
  try {
    setUploading(true);
    blob = await getPictureBlob(img);

    const ref = await storage.ref().child(uuid.v4());
    const snapshot = await ref.put(blob);
    console.log("link path");
    return await snapshot.ref.getDownloadURL();
  } catch (e) {
    alert(e.message);
  } finally {
    blob.close();
    setUploading(false);
  }
};

const UpdateImage = async (img) => {
  setImage(result.uri);
  let imgUrl = await uploadImageToBucket(img);
  if (imgUrl === null && userData.photoURL) {
    imgUrl = userData.photoURL;
  }
  firebase
    .firestore()
    .collection("users")
    .doc(firebase.auth().currentUser.uid)
    .update({
      photoURL: imgUrl,
    })
    .then(() => console.log("user Upadted"));
};

useEffect(() => {
  getPermission();
}, []);
useEffect(() => {
  getUserData();
}, []);


推荐阅读