无法在React Js中将Firebase存储下载URL添加到同一Firestore文档中。

huangapple go评论109阅读模式
英文:

Couldn't add firebase storage download url in same firestore document in React Js

问题

以下是您要翻译的代码部分:

  1. I'm trying to upload multiple images to firebase storage and store those urls in one firestore document as an array of strings, but I couldn't add all urls in the same firestore document. Instead, it's creating different documents for each firebase storage Url.
  2. ImageUpload.js
  3. import React, { useState } from "react";
  4. import { toast } from "react-toastify";
  5. import { db, storage } from "../firebase.config";
  6. import { ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";
  7. import { collection, addDoc, arrayUnion, FieldValue, updateDoc } from "firebase/firestore";
  8. import { useNavigate } from "react-router-dom";
  9. import "./style.css";
  10. function ImageUpload() {
  11. const [allImages, setAllImages] = useState([]);
  12. function handleAllImage(e) {
  13. e.preventDefault();
  14. setAllImages(e.target.files);
  15. console.log(e.target.files);
  16. }
  17. function MutipleUpload(e) {
  18. e.preventDefault();
  19. try {
  20. const docRef = collection(db, "products");
  21. for (let i = 0; i < allImages.length; i++) {
  22. const storageRef = ref(storage, `productImages/${allImages[i].name}`);
  23. const uploadTask = uploadBytesResumable(storageRef, allImages[i], {
  24. contentType: allImages[i].type,
  25. });
  26. uploadTask.on(
  27. "state_changed",
  28. (snapshot) => {
  29. const progress =
  30. (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
  31. console.log(progress);
  32. },
  33. (error) => toast.error(error.message),
  34. () => {
  35. getDownloadURL(uploadTask.snapshot.ref).then(
  36. async (downloadURL) => {
  37. await addDoc(docRef, {
  38. imgUrl: arrayUnion(downloadURL),
  39. });
  40. }
  41. );
  42. }
  43. );
  44. }
  45. toast.success("product added successfully!");
  46. } catch (error) {
  47. console.log(error.message);
  48. }
  49. }
  50. return (
  51. <>
  52. <input
  53. type="file"
  54. multiple="multiple"
  55. onChange={handleAllImage}
  56. required
  57. />
  58. <button onClick={MutipleUpload} type="submit" className="buy__btn mt-3">
  59. Add Image
  60. </button>
  61. </>
  62. );
  63. }
  64. export default ImageUpload;

请注意,代码中的 HTML 标签和 JavaScript 部分已经分开以便更好地理解。如果有任何问题,请告诉我。

英文:

I'm trying to upload multiple images to firebase storage and store those urls in one firestore document as an array of strings, but I couldn't add all urls in same firestore document. Instead it's creating different documents for each firebase storage Url.

ImageUpload.js

  1. import React, { useState } from &quot;react&quot;;
  2. import { toast } from &quot;react-toastify&quot;;
  3. import { db, storage } from &quot;../firebase.config&quot;;
  4. import { ref, uploadBytesResumable, getDownloadURL } from &quot;firebase/storage&quot;;
  5. import {collection ,addDoc ,arrayUnion ,FieldValue ,updateDoc} from &quot;firebase/firestore&quot;;
  6. import { useNavigate } from &quot;react-router-dom&quot;;
  7. import &quot;./style.css&quot;;
  8. function ImageUpload() {
  9. const [allImages, setAllImages] = useState([]);
  10. function handleAllImage(e) {
  11. e.preventDefault();
  12. setAllImages(e.target.files);
  13. console.log(e.target.files);
  14. }
  15. function MutipleUpload(e) {
  16. e.preventDefault();
  17. try {
  18. const docRef = collection(db, &quot;products&quot;);
  19. {
  20. for (let i = 0; i &lt; allImages.length; i++) {
  21. const storageRef = ref(storage, `productImages/${allImages[i].name}`);
  22. const uploadTask = uploadBytesResumable(storageRef, allImages[i], {
  23. contentType: allImages[i].type,
  24. });
  25. uploadTask.on(
  26. &quot;state_changed&quot;,
  27. (snapshot) =&gt; {
  28. const progress =
  29. (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
  30. console.log(progress);
  31. },
  32. (error) =&gt; toast.error(error.message),
  33. () =&gt; {
  34. getDownloadURL(uploadTask.snapshot.ref).then(
  35. async (downloadURL) =&gt; {
  36. await addDoc(docRef, {
  37. imgUrl: arrayUnion(downloadURL),
  38. });
  39. }
  40. );
  41. }
  42. );
  43. }
  44. }
  45. toast.success(&quot;product added successfully!&quot;);
  46. } catch (error) {
  47. console.log(error.message);
  48. }
  49. }
  50. return (
  51. &lt;&gt;
  52. &lt;input
  53. type=&quot;file&quot;
  54. multiple=&quot;multiple&quot;
  55. onChange={handleAllImage}
  56. required
  57. /&gt;
  58. &lt;button onClick={MutipleUpload} type=&quot;submit&quot; className=&quot;buy__btn mt-3&quot;&gt;
  59. Add Image
  60. &lt;/button&gt;
  61. &lt;/&gt;
  62. );
  63. }
  64. export default ImageUpload;

Extra text cause error "It looks like your post is mostly code; please add some more details."

答案1

得分: 0

以下是您要的代码部分的翻译:

  1. 问题出在这段代码中
  2. 每次调用 `addDoc` Firestore 都会在集合中创建一个新文档
  3. 如果您想要[更新现有文档](https://firebase.google.com/docs/firestore/manage-data/add-data#update-data),您需要执行以下步骤:
  4. 1. 记住要更新的文档的 ID
  5. 2. 然后对该文档调用 `updateDoc`
  6. 要生成文档 ID 一次然后随时进行更新请查看[添加文档](https://firebase.google.com/docs/firestore/manage-data/add-data#add_a_document)文档中的第三个代码片段:
  7. &gt; 在某些情况下创建一个带有自动生成的 ID 的文档引用然后稍后使用引用是有用的对于这种用例您可以调用 `doc()`
  8. &gt; ```javascript
  9. &gt; import { collection, doc, setDoc } from "firebase/firestore";
  10. &gt;
  11. &gt; // 添加带有生成的 ID 的新文档
  12. &gt; const newCityRef = doc(collection(db, "cities"));
  13. &gt;
  14. &gt; // 稍后...
  15. &gt; await setDoc(newCityRef, data);
  16. &gt;```
  17. 应用于您的用例可能会类似于这样
  18. ```javascript
  19. const docRef = collection(db, "products");
  20. const newDocRef = doc(docRef); // 生成一个新文档的引用
  21. for (let i = 0; i < allImages.length; i++) {
  22. const storageRef = ref(storage, `productImages/${allImages[i].name}`);
  23. const uploadTask = uploadBytesResumable(storageRef, allImages[i], {
  24. contentType: allImages[i].type,
  25. });
  26. uploadTask.on(
  27. "state_changed",
  28. (snapshot) => {
  29. const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
  30. console.log(progress);
  31. },
  32. (error) => toast.error(error.message),
  33. () => {
  34. getDownloadURL(uploadTask.snapshot.ref).then(
  35. async (downloadURL) => {
  36. await setDoc(newDocRef, {
  37. imgUrl: arrayUnion(downloadURL),
  38. }, { merge: true }); // 告诉它将值合并到任何现有文档中
  39. }
  40. );
  41. }
  42. );
  43. }

希望这有所帮助!

英文:

The problem is in this code:

  1. getDownloadURL(uploadTask.snapshot.ref).then(
  2. async (downloadURL) =&gt; {
  3. await addDoc(docRef, {
  4. imgUrl: arrayUnion(downloadURL),
  5. });
  6. }
  7. );

Every time you call addDoc, Firestore create a new document in the collection.

If you instead want update an existing document, you have to:

  1. Remember the document ID for the document you want to update.
  2. Then call updateDoc on that document

To generate a document ID once and then update that all the time, have a look at the third code snippet in the documentation on adding a document:
> In some cases, it can be useful to create a document reference with an auto-generated ID, then use the reference later. For this use case, you can call doc():
>
&gt; import { collection, doc, setDoc } from &quot;firebase/firestore&quot;;
&gt;
&gt; // Add a new document with a generated id
&gt; const newCityRef = doc(collection(db, &quot;cities&quot;));
&gt;
&gt; // later...
&gt; await setDoc(newCityRef, data);
&gt;

Applied to your use-case, that could look something like this:

  1. const docRef = collection(db, &quot;products&quot;);
  2. const newDocRef = doc(docRef); // &#128072; generate reference to a single new doc
  3. {
  4. for (let i = 0; i &lt; allImages.length; i++) {
  5. const storageRef = ref(storage, `productImages/${allImages[i].name}`);
  6. const uploadTask = uploadBytesResumable(storageRef, allImages[i], {
  7. contentType: allImages[i].type,
  8. });
  9. uploadTask.on(
  10. &quot;state_changed&quot;,
  11. (snapshot) =&gt; {
  12. const progress =
  13. (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
  14. console.log(progress);
  15. },
  16. (error) =&gt; toast.error(error.message),
  17. () =&gt; {
  18. getDownloadURL(uploadTask.snapshot.ref).then(
  19. async (downloadURL) =&gt; {
  20. await setDoc(newDocRef, { // &#128072; Call setDoc, since the doc may not exist yet
  21. imgUrl: arrayUnion(downloadURL),
  22. }, { merge: true }); // &#128072; tell it to merge values into any existing doc
  23. }
  24. );
  25. }
  26. );
  27. }
  28. }

huangapple
  • 本文由 发表于 2023年2月19日 02:58:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/75495688.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定