How do I dynamically create a Firebase Storage reference based on previous reference value?

删除回忆录丶 提交于 2020-07-16 10:43:28

问题


Here's a brief overview of the process that I need help with:

  1. Client uploads images to Firebase Storage at users/displayName/uid/ - this step is clear and done. No help needed on this one.

  2. Then, client presses "request a quote" button which saves the URLs of the images (the ones that were uploaded to Storage in step 1) to Firebase Firestore - this step is clear and done. No help needed on this one.

  3. After the URLs are saved to the Firestore, I want those images from Step 1 to be moved within the same bucket of the Storage to users/displayName/uid/order1. So, basically, from users/displayName/uid/ to users/displayName/uid/order1. - I need help with writing out the right Javascript code for this action. I tried the code snippet from below but it does not seem to work, not sure what is wrong.

  4. At some point in the future, the same client will need to upload more images thus repeating the first 3 steps above. However, on the 3rd step, I will need his images to be moved from users/displayName/uid/ to users/displayName/uid/order2. The problem lies in me not knowing how to render the last part of the directory as order2 and not the same order1 as in the 3rd step. The number after "order" will basically need to increase every time the client repeats the steps. I have no idea of how to write out the right code for this. Please help.

If it helps, here are my functions that upload images to Firebase Storage and Firebase Firestore:

// Upload to Storage

    handleUpload = () => {

        this.state.files.forEach((file) => {
            const storageRef = firebase.storage().ref(`users/${this.state.displayName}/${this.state.uid}/${file.name}`);
            var task = storageRef.put(file)


            // Progress

            task.on("state_changed", snapshot => {

                const progress = Math.round(
                    (snapshot.bytesTransferred / snapshot.totalBytes) * 100
                );
                this.setState({ progress });
            },


                // Error

                error => {
                    console.log(error);
                },


                // Additional function to update state with all files uploaded

                () => {
                    firebase.storage()
                        .ref(`users/${this.state.displayName}/${this.state.uid}`)
                        .child(file.name)
                        .getDownloadURL()
                        .then(url => {
                            this.setState(state => {
                                const urls = [...state.urls, url];
                                return {
                                    urls
                                };
                            });
                        });


                    // Empty file upload

                    this.setState({ progress: 0 })
                    this.setState({ files: [] })
                }
            );

        })


    };


// Saving to Firestore - PRESS GET A QUOTE TO ACTIVATE

    async saveToFirestore() {

        // Getting it all from storage first        
        const listRef = firebase.storage().ref(`users/${this.state.displayName}/${this.state.uid}`)

        const res = await listRef.listAll()
        const urlPromises = res.items.map((itemRef) => {
            return itemRef.getDownloadURL()
        })
        const urls = await Promise.all(urlPromises)


        // Then, we save it all to Firestore
        firebase.firestore().collection('Documents/').doc(this.state.displayName).set({
            documents: urls,
            quote: 'pending',
            name: this.state.displayName,
            email: this.state.email,
            emailVerified: this.state.emailVerified,
            createdAt: firebase.firestore.FieldValue.serverTimestamp(),
            userId: this.state.uid
        })
            .then(() => {

                const listRef = firebase.storage().ref(`users/${this.state.displayName}/${this.state.uid}`)

                listRef.listAll().then((res) => {

                    console.log(res)

                    res.items.forEach(function (item) {

                        console.log(item)

                        firebase.storage().ref(`users/${this.state.displayName}/${this.state.uid}/order1/${item.name}`).put(item);
                    });
                }).catch(function (error) {
                    // Uh-oh, an error occurred!
                });



                this.setState({ quote: "pending" })

                firebase.firestore().collection('Documents/').doc(this.state.displayName).get().then((doc) => {

                    if (doc.exists) {
                        doc.data().documents.forEach(url => {
                            this.setState(state => {
                                const documents = [...state.documents, url];
                                return {
                                    documents
                                };
                            });
                        })


                        this.setState({ createdAt: doc.data().createdAt.toDate().toString() })

                    } else {
                        // doc.data() will be undefined in this case
                        console.log("No such document!");
                    }
                }).catch(function (error) {
                    console.log("Error getting document:", error);
                });
            })
            .catch((error) => {
                console.error("Error writing document: ", error);
            });

    }

Please let me know if anything else is needed.

Thank you very much!


回答1:


As far as I can tell, you have two parts to your question:

  1. Determine the folder for the next order
  2. Write all files from the root to this folder

I'll focus on the first step in this answer.

Determine the folder for the next order

To determine the next order? folder, we'll get a list of all files/folders from Storage, and then filter them to determine the highest number in there:

var ref = firebase.storage().ref("62849565");

ref.listAll().then(function(res) {
  // Determine the next order folder
  const orderFolders = res.prefixes.filter((folder) => folder.name.match(/^order(\d+)$/));
  let highestOrderNumber = 0;
  orderFolders.forEach((folder) => {
    const match = folder.name.match(/^order(\d+)$/);
    const number = parseInt(match[1]);
    if (number > highestOrderNumber) {
      highestOrderNumber = number;
    }
  })
  const nextOrderFolderPrefix = "order" + (highestOrderNumber+1);

  // Move the files from the root to the new folder
  res.items.forEach(function(itemRef) {
    // TODO: read file from root and write it to the next order folder
  });
}).catch(function(error) {
  console.error(error);
});

(Also see this jsbin where I created/tested this code)

In the above:

  1. The res.prefixes.filter((folder) => folder.name.match(/^order(\d+)$/)) ensures we only consider folders following the order1 naming pattern.
  2. We then loop over the folders to find the highest number.
  3. We them determine the path for the next folder.

Write all files from the root to the new folder

The TODO in this code is to move the actual file. There is no operation in Cloud Storage (or its Firebase SDK) to move a file. So you will have to do a sequence of read the file, write it to its new location, and removing it from its original location. I recommend searching around a bit, as I'm pretty sure this must have been asked before.



来源:https://stackoverflow.com/questions/62849565/how-do-i-dynamically-create-a-firebase-storage-reference-based-on-previous-refer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!