【问题标题】:Upload more images from react-native app to firebase将更多图像从 react-native 应用程序上传到 firebase
【发布时间】:2021-08-05 07:10:17
【问题描述】:

我正在尝试将多个图像从 react-native 上传到 firebase。我解决这个问题的方法是使用expo image picker multiple - by monstrodev(参见snack.io here

我设法让它工作,并设法从“即兴”相机胶卷中选择多张照片。它们在添加屏幕中加载良好,但我找不到如何正确上传它们的解决方案。

        export default function Add(props) {

        const [name, setName] = useState("");
        const [photos, setPhotos] = useState(null);



        const uploadImage = async () => {
        const uri = photos[0].uri; // -> uri is like this because 'media' is an array with objects inside that contain name, type, and uri each, and I only need uri of each oject.
        const childPath = `data/${firebase.auth().currentUser.uid}/${Math.random().toString(36)}`;
        console.log(childPath);
        const response = await fetch(uri);
        const blob = await response.blob();

        const upload = firebase
            .storage()
            .ref()
            .child(childPath)
            .put(blob);

        const uploadProgress = snapshot => {
            console.log(`transferred: ${snapshot.bytesTransferred}`)
            };


            const uploadComplete = () => {
                    upload.snapshot.ref.getDownloadURL().then((snapshot) =>{
                        addPost(snapshot);
                        console.log(snapshot);
                    })
            };

            const uploadError = snapshot => {
                console.log(snapshot);
            };

            upload.on("state_changed", uploadProgress, uploadError, uploadComplete );

            
            };



        const addPost = (downloadURL) => {  
            firebase.firestore() 
            .collection("allPosts")
            .collection(firebase.auth().currentUser.uid)
            .collection('userPosts')
            .add({
            
                downloadURL,
                name,
            }).then((function () {
                props.navigation.popToTop()
            }))
        } 


        useEffect(() => {
        const {params} = props.route;
        if(params) {
        const {photos} = params;
        if(photos) setPhotos(photos)
        delete params.photos
        }

        }, [{photos}]) // This useEffect updates when coming back from the ImageBrowserScreen (can be found in snack.io, it's exactly the same) 

主要问题是,假设我选择了 3 张照片。如果我 console.log(photos) 我得到这个:

  Array [
   Object {
    "name": "name1.JPG",
    "type": "image/jpg",
    "uri": "file:///name1.jpg",
   },
   Object {
    "name": "name2.JPG",
    "type": "image/jpg",
    "uri": "file:///name2.jpg",
   },
   Object {
    "name": "name3.JPG",
    "type": "image/jpg",
    "uri": "file:///name3.jpg",
   },
  ]

我唯一可以让它工作的是,给出 uri 的确切路径(例如照片 [0].uri),否则会出现网络错误。但这只会上传第一个对象/照片。我还尝试映射照片状态并将所有 uri 返回到一个数组中并将其用作 const uri,但这显然不起作用,因为 uri 只需要一个字符串。所以我需要为每个 uri 运行该函数,以便能够获取一个 downloadURL 并存储它们。

编辑:

const uploadImage = async (photo) => {
const uri = photo.uri;
const childPath = `data/${
  firebase.auth().currentUser.uid
}/${Math.random().toString(36)}`;
console.log(childPath);
const response = await fetch(uri);
const blob = await response.blob();

const snapshot = await firebase.storage().ref().child(childPath).put(blob);
const downloadURL = await snapshot.ref.getDownloadURL();
imgs.push(downloadURL)
};

 const uploadPhotos = async () => {
  await Promise.all(photos.map(p=>uploadImage(photo)).then(addPost())
};

【问题讨论】:

    标签: reactjs firebase react-native google-cloud-firestore


    【解决方案1】:

    您能否通过循环遍历所有照片并分别上传它们来尝试。理想情况下使用Promise.all 并行上传它们:

    
     const addPost = async (downloadURLs) => {  
                await firebase.firestore() 
                .collection("allPosts")
                .collection(firebase.auth().currentUser.uid)
                .collection('userPosts')
                .add({
                    downloadURLs,
                    name,
                })
         props.navigation.popToTop()
            } 
    
      const uploadImage = async (photo) => {
        const uri = photo.uri;
        const childPath = `data/${
          firebase.auth().currentUser.uid
        }/${Math.random().toString(36)}`;
        console.log(childPath);
        const response = await fetch(uri);
        const blob = await response.blob();
    
        const snapshot = await firebase.storage().ref().child(childPath).put(blob);
        const downloadURL = await snapshot.ref.getDownloadURL();
        return downloadURL
      };
    
      const uploadPhotos = async () => {
          const downloadURLs=await Promise.all(photos.map(p=>uploadImage(photo))
    
          await addPost(downloadURLs);
      };
    

    【讨论】:

    • 非常适合将文件上传到存储,谢谢!我在将实际帖子添加到 Firestore 时遇到了问题。据我所见,如果 addPost() 在uploadImage 中,它将为每个图像运行该函数(在firestore 中为每个图像创建一个帖子)而不是一个帖子,所有图像都在一个数组字段中。所以我尝试了这个:从uploadImage中删除了addPost,而是在promise解决后添加它。对于uploadImage 中的每个downloadURL,将其推送到数组状态。但是从我的 console.logs 中,我只在几秒钟后得到了 downloadURL,因此数组是空的。
    • 我已经用代码更新了答案,该代码也应该正确添加帖子。
    • 我试过了,还是不行。同样,为每个不同的 downloadURL 上传不同的帖子。我认为最理想的解决方案是将所有下载 URL 添加到前端的数组中,然后将该数组添加到 post。但正如我上面所说,无法让它工作。我必须想办法等到所有链接都在数组中,现在数组被空发送到firestore。
    • 我坚持你希望它们分开保存。但是您想要一个 post 元素,您可以按照您所说的将所有 DownloadURL 保存到一个数组中,然后将该数组添加到 post 对象中。或者您可以创建一次 post 对象并将链接保存在其中的嵌套部分中。
    • 你可以用更新答案的代码试试吗。
    猜你喜欢
    • 2016-11-20
    • 2018-01-14
    • 2022-10-18
    • 2020-06-21
    • 1970-01-01
    • 2021-09-28
    • 1970-01-01
    • 2020-04-10
    • 2023-03-31
    相关资源
    最近更新 更多