【问题标题】:How do I dynamically create a Firebase Storage reference based on previous reference value?如何根据以前的参考值动态创建 Firebase 存储参考?
【发布时间】:2020-11-01 02:19:49
【问题描述】:

以下是我需要帮助的流程的简要概述:

  1. 客户端将图像上传到位于 users/displayName/uid/ 的 Firebase 存储 - 这一步很清楚并完成。这个不需要帮助。

  2. 然后,客户端按下“请求报价”按钮,将图像的 URL(在步骤 1 中上传到存储的图像)保存到 Firebase Firestore - 这一步很清楚并完成。这个不需要帮助。

  3. 在将 URL 保存到 Firestore 后,我希望将步骤 1 中的这些图像移动到 Storage 的同一存储桶中到 users/displayName/uid/order1。所以,基本上,从 users/displayName/uid/ 到 users/displayName/uid/order1。 - 我需要帮助才能为此操作编写正确的 Javascript 代码。我尝试了下面的代码 sn-p 但它似乎不起作用,不知道是什么问题。

  4. 在未来的某个时候,同一个客户端将需要上传更多图片,从而重复上面的前 3 个步骤。但是,在第三步,我需要将他的图像从 users/displayName/uid/ 移动到 users/displayName/uid/order2。问题在于我不知道如何将目录的最后一部分呈现为 order2,而不是与第三步中的 order1 相同。每次客户重复这些步骤时,“订单”后的数字基本上都需要增加。我不知道如何为此编写正确的代码。请帮忙。

如果有帮助,以下是我将图像上传到 Firebase Storage 和 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);
            });

    }

如果还有什么需要请告诉我。

非常感谢!

【问题讨论】:

  • “上传到存储后,他们会执行将这些图像上传到 Firebase Firestore 的操作。”您可以编辑您的问题以显示代码吗?除非该代码当然与问题无关,但在这种情况下:请同时更新您的问题描述以不再需要它。一般来说,我很难解析您的用例,因为发生了很多事情。您越能缩小范围,我们就越有可能提供帮助。
  • 您的问题是“如何根据旧路径和转换确定图像的新路径?”或者是:“我如何通过 Firebase Storage API 确定下一个可用的文件夹名称?”
  • 您好弗兰克,感谢您的回复。图像如何上传到 Firestore 的代码无关紧要。不,我不想根据图像的旧路径确定新路径,因为所有图像首先上传到存储在 users/userDisplayName/uid 处。在某个操作(客户请求报价)之后,它们将作为订单、订单 1、订单 2、订单 3 等移动到各自的位置。我的问题是如何动态创建这些新路径(订单 1、订单 2、订单 3 等)或以编程方式用于图像 - users/userDisplayName/uid/order1。我也会在上面添加更多细节。谢谢。
  • 嗨弗兰克,我已经更新了上面的问题,并添加了我正在尝试实施的过程的简要概述。请让我知道您是否可以提供帮助或是否需要其他任何东西。谢谢。
  • 此时您的问题 方式 太长,但通过快速扫描,它仍然显示为:“如何通过 Firebase 存储 API 确定下一个可用文件夹名称?”你能确认一下吗?

标签: javascript reactjs firebase url firebase-storage


【解决方案1】:

据我所知,您的问题分为两部分:

  1. 确定下一个订单的文件夹
  2. 将根目录下的所有文件写入此文件夹

我将重点介绍此答案的第一步。

确定下一个订单的文件夹

要确定下一个order? 文件夹,我们将从存储中获取所有文件/文件夹的列表,然后过滤它们以确定其中的最大数量:

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);
});

(另见 jsbin 我创建/测试此代码的地方)

在上面:

  1. res.prefixes.filter((folder) => folder.name.match(/^order(\d+)$/)) 确保我们只考虑遵循 order1 命名模式的文件夹。
  2. 然后我们遍历文件夹以找到最大的数字。
  3. 我们确定下一个文件夹的路径。

将根目录下的所有文件写入新文件夹

此代码中的TODO 是移动实际文件。 Cloud Storage(或其 Firebase SDK)中没有移动文件的操作。因此,您必须执行一系列读取文件,将其写入新位置,然后将其从原始位置删除。我建议搜索一下,因为我很确定这之前一定有人问过。

【讨论】:

  • 嗨弗兰克,精彩、完美的代码,非常感谢!唯一剩下的问题是第二部分(将所有文件从根目录写入新文件夹)。我已阅读所有文章,但找不到代码示例。仅对文档页面的引用。我尝试了这段代码,但它说它需要一个文件或 blob 出错。这是代码: res.items.forEach((itemRef) => { firebase.storage().ref(users/${this.state.displayName}/${this.state.uid}/order).put(itemRef) });任何想法为什么这不起作用以及什么会起作用?谢谢。
  • 嗨弗兰克,请看我刚刚发布的这个问题 - stackoverflow.com/questions/62865814/…
  • 好的,关于如何将文件从根目录复制到文件夹有什么想法吗?
  • 为什么你在上面的代码中匹配同一个 RegEx 两次? (文件夹) => 文件夹.name.match(/^order(\d+)$/)); AND const match = folder.name.match(/^order(\d+)$/);
  • 第一个是找到定义订单的过滤器,第二个是从中提取数字。如果您愿意,您可以将其重构为只执行一次正则表达式匹配,甚至合并过滤器和循环,但代码的工作方式相同。
猜你喜欢
  • 1970-01-01
  • 2019-01-04
  • 2016-10-17
  • 1970-01-01
  • 2019-04-25
  • 2018-07-22
  • 1970-01-01
  • 2022-07-01
  • 2017-12-11
相关资源
最近更新 更多