如何將從firebase存儲上傳的圖像保存到firestore數據庫中的currentUser

Halp_am_stuck

我不確定如何獲取上傳到 firebase 存儲的圖像 url 並將其保存到 firestore 數據庫。目前我有一個配置文件組件,用於存儲用戶將照片上傳到 firebase 存儲的邏輯。我有一個偵聽用戶更改的 UserContext 文件。以及創建用戶的 Firebase.utils。

Firebase.utils 文件:

import firebase from 'firebase/compat/app';
import 'firebase/compat/firestore';
import 'firebase/compat/auth';
import "firebase/compat/storage";

const config = {
    apiKey: "",
    authDomain: "",
    projectId: "",
    storageBucket: "",
    messagingSenderId: "",
    appId: "",
    measurementId: ""
};

firebase.initializeApp(config);

export const createUserProfileDocument = async (userAuth, additionalData) => {
    // If user is not signed in do nothing
    if (!userAuth) return;

    const userRef = firestore.doc(`users/${userAuth.uid}`)

    const snapShot = await userRef.get()

    if (!snapShot.exists) {
        // Added photoURL @@@
        const { displayName, email, photoURL } = userAuth;
        const createdAt = new Date();

        try {
            await userRef.set({
                displayName,
                email,
                createdAt,
                photoURL,
                ...additionalData
            })
        } catch (error) {
            console.log('error creating user', error.message)
        }
    }

    return userRef;
}

export const auth = firebase.auth();
export const firestore = firebase.firestore();
const storage = firebase.storage();; 

export { storage, firebase as default };

用戶上下文文件:
import React, { useContext, useState, useEffect } from 'react';
import { auth, createUserProfileDocument } from "../Firebase/Firebase.utils";

const UserContext = React.createContext(null);
const UserUpdateContext = React.createContext();
const UserUpdateNameContext = React.createContext();
const UserUpdateEmailContext = React.createContext();

export const useUserContext = () => {
    // useContext hook 
    return useContext(UserContext);
}

export const useUserContextUpdate = () => {
    // useContext hook - toggleUser signout function
    return useContext(UserUpdateContext)
}

export const useUserNameUpdate = () => {
    // useContext hook - update user displayName
    return useContext(UserUpdateNameContext)
}

export const useUserEmailUpdate = () => {
    // useContext hook - update user email
    return useContext(UserUpdateEmailContext)
}

export const UserContextProvider = ({ children }) => {
    const [currentUser, setUser] = useState(null);
    let unsubscribeFromAuth = null;
    console.log(currentUser)

    useEffect(() => {
        unsubscribeFromAuth = auth.onAuthStateChanged(async userAuth => {
            if (userAuth) {
                const userRef = await createUserProfileDocument(userAuth);

                userRef.onSnapshot(snapShot => {
                    setUser({
                        id: snapShot.id,
                        ...snapShot.data()
                    });
                });
            } else {
                setUser(null)
                // setUser({ currentUser: userAuth }) OBJECTS ARE TRUTHY 
            }
        });

        return () => {
            unsubscribeFromAuth();
        };
    }, [])
    console.log(unsubscribeFromAuth)

    const toggleUser = () => {
        auth.signOut()
            .then(() => {
                setUser(null)
            })
            .catch(e => console.log('There was a error:'(e)))
    }
    // console.log(currentUser)

    // Get current window width
    const useWindowWidth = () => {
        const [width, setWidth] = useState(window.innerWidth)
        useEffect(() => {
            const handleResize = () => setWidth(window.innerWidth)
            window.addEventListener('resize', handleResize)
            return () => {
                window.removeEventListener('resize', handleResize)
            }
        })
        return width
    }
    const width = useWindowWidth();

    // Slice off end of displayName if reaches a certain length
    const sliceDisplayName = (currentUser) => {
        if (currentUser) {
            const displayName = currentUser.displayName;
            return (
                width >= 1441 ? displayName.substring(0, 16) + '...'
                    : width <= 1440 && width >= 769 ? displayName.substring(0, 14) + '...'
                        : width <= 768 ? displayName.substring(0, 7) + '...'
                            : displayName
            )
        } else (console.log("No user found :("))
    }
    // console.log(sliceDisplayName(currentUser))

    // Slice off end of email if reaches a certain length
    const sliceEmail = (currentUser) => {
        if (currentUser) {
            const email = currentUser.email;
            return (
                width >= 1441 ? email.substring(0, 16) + '...'
                    : width <= 1440 && width >= 769 ? email.substring(0, 14) + '...'
                        : width <= 768 ? email.substring(0, 7) + '...'
                            : email
            )
        } else (console.log("No user found :("))
    }
    // console.log(sliceEmail(currentUser))

    return (
        <UserContext.Provider value={currentUser} >
            <UserUpdateContext.Provider value={toggleUser} >
                <UserUpdateNameContext.Provider value={sliceDisplayName} >
                    <UserUpdateEmailContext.Provider value={sliceEmail} >
                        {children}
                    </UserUpdateEmailContext.Provider >
                </UserUpdateNameContext.Provider >
            </UserUpdateContext.Provider >
        </UserContext.Provider >
    )
};

配置文件組件:
import React, { useState } from 'react';
import ReactTooltip from 'react-tooltip';
import { useUserContext, useUserContextUpdate, useUserNameUpdate } from '../../Utilities/Context/UserContext';
import { storage } from "../../Utilities/Firebase/Firebase.utils";
import { ref, uploadBytesResumable, getDownloadURL } from "firebase/storage"; 
import ActivityFeed from '../../../src/components/ActivityFeed/ActivityFeed';
import Post from '../../../src/components/Post/Post';

import './Profile.css';

const Profile = ({ imageDate }) => {
    const currentUser = useUserContext(); // Current user
    const sliceDisplayName = useUserNameUpdate(); // Window width < (width) ? update displayName length
    const [image, setImage] = useState("");
    const [url, setUrl] = useState("");

    // Listen for state changes, errors, and completion of the upload.
    const handleUpload = () => {
        const uploadTask = storage.ref(`images/${image.name}`).put(image);
        uploadTask.on('state_changed',
            (snapshot) => { console.log(snapshot) },
            (error) => {
                switch (error.code) {
                    case 'storage/unauthorized':
                        break;
                    case 'storage/canceled':
                        break;
                    case 'storage/unknown':
                        break;
                }
            },
            (e) => {
                storage
                    .ref("images")
                    .child(image.name)
                    .getDownloadURL(uploadTask.snapshot.ref)
                    .then(url => {
                        setUrl(url);
                        console.log('File available at', url);
                    })
            }
        );
    }
    console.log("image: ", image);
    console.log(image.lastModifiedDate) // Image date uploaded. image.lastmodifiedDate === undefined ? 
    console.log(url)

    const handleUploadChange = e => { // Maybe inside this function i can do the logic for recent activity and 0 photos +1
        if (e.target.files[0]) {
            setImage(e.target.files[0]);
        }
    };

    return (
        <div className="container-flex">
            <div className="top-content-container w-100">
                <div className="bot-content-wrapper px-1 py-2 mx-lg-auto d-flex flex-column flex-lg-row">
                    <div className="w-spacer profile-image-wrapper position-relative">
                        {
                            currentUser ?
                                <input
                                    type="file"
                                    for="Upload Image"
                                    accept="image/*"
                                    name="image"
                                    id="file"
                                    onChange={handleUploadChange}
                                    onClick={handleUploadChange}
                                    style={{ display: "none" }}
                                />
                                : ''
                        
                        }
                        <label for="file">  
                            {
                                url.length <= 0 ?
                                    <img
                                        id='myimg'
                                        className="profile-image-default profile-image d-block"
                                        alt=""
                                    />
                                : currentUser ?
                                    <>
                                        <img
                                            id='myimg'
                                            className="profile-image d-block"
                                            src={url}
                                            alt=""
                                            data-tip="Click me to update profile picture!" />                                    
                                        <ReactTooltip place="top" type="dark" effect="float" />
                                    </>
                                :
                                    <img
                                        id='myimg'
                                        className="profile-image-default profile-image d-block"
                                        alt=""
                                    />
                            }
                        </label>
                    </div>
                    <div className="d-flex flex-column flex-lg-row align-items-lg-center w-lg-75 m-l-4">
                        <div className="d-flex flex-column flex-lg-row ml-auto pr-1 m-r-md-vw">
                            <div className="m-r-md">
                                <div className="d-flex flex-column w-100 m-r-6">
                                    <div>
                                        {
                                            currentUser ?
                                                <h2
                                                    data-tip={currentUser.displayName}>
                                                    {sliceDisplayName(currentUser)}
                                                    <span><ReactTooltip place="top" type="dark" effect="float" /></span>
                                                </h2>
                                                :
                                                <h2>No User</h2>
                                        }
                                    </div>
                                    <div className="d-flex flex-column flex-lg-row">
                                        <div className="">
                                            <i className="bi bi-people"></i>
                                            <span className="banner-list-font mx-1">0 friends</span>
                                        </div>
                                        <div className="mx-lg-2">
                                            <i className="bi bi-star"></i>
                                            <span className="banner-list-font mx-1">0 reviews</span>
                                        </div>
                                        <div className="">
                                            <i className="bi bi-camera"></i>
                                            <span className="banner-list-font mx-1">0 photos</span>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <hr className=" d-lg-none" style={{ color: '#0a0a0a' }}></hr>
                            <div className="ml-3">
                                <div className="update-profile-wrapper grey-line-break d-flex flex-column m-l">
                                    <div className="">
                                        {
                                            image.name !== undefined ?
                                                <button
                                                    className="banner-list-font"
                                                    onClick={handleUpload}
                                                    //  onClick={() => {
                                                    //      handleUpload();
                                                    //      forceUpdate();
                                                    //  }}
                                                >Add Profile Photo
                                                </button>
                                                : ''
                                        }
                                    </div>
                                    <div className="">
                                        <a className="banner-list-font" href='#'>Update Your Profile</a>
                                    </div>
                                    <div className="">
                                        <a className="banner-list-font" href='#'>Find Friends</a>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div className="bot-content-container px-1 py-4 custom-padding">
                <div className="bot-content-wrapper mx-lg-auto d-flex flex-column flex-lg-row">
                    <div className="sidebar d-flex flex-column mx-auto mx-lg-0 mt-lg-5 py-lg-2 px-2">
                        {
                            currentUser ?
                                <h4 className="mb-3">{currentUser.displayName}</h4>
                                :
                                <h4 className="mb-3">No User</h4>
                        }
                        <ul className="p-0">
                            <a className="cursor-pointer text-decoration-none">
                                <li className="d-flex flex-row sidebar-item sidebar-list-font">
                                    <i className="mx-2 bi bi-person-badge"></i>
                                    <h5 className="sidebar-list-font">Overview</h5>
                                </li>
                                <hr style={{ color: '#0a0a0a' }}></hr>
                            </a>
                            <a className="cursor-pointer text-decoration-none">
                                <li className="d-flex flex-row sidebar-item sidebar-list-font">
                                    <i className="mx-2 bi bi-person-plus"></i>
                                    <h5 className="sidebar-list-font">Friends</h5>
                                </li>
                                <hr style={{ color: '#0a0a0a' }}></hr>
                            </a>
                            <a className="cursor-pointer text-decoration-none">
                                <li className="d-flex flex-row sidebar-item sidebar-list-font">
                                    <i className="mx-2 bi bi-award mx-1"></i>
                                    <h5 className="sidebar-list-font">Reviews</h5>
                                </li>
                                <hr style={{ color: '#0a0a0a' }}></hr>
                            </a>
                            <a className="cursor-pointer text-decoration-none">
                                <li className="d-flex flex-row sidebar-item sidebar-list-font">
                                    <i className="mx-2 bi bi-lightbulb"></i>
                                    <h5 className="sidebar-list-font">Tips</h5>
                                </li>
                                <hr style={{ color: '#0a0a0a' }}></hr>
                            </a>
                            <a className="cursor-pointer text-decoration-none">
                                <li className="d-flex flex-row sidebar-item sidebar-list-font">
                                    <i className="mx-2 bi bi-bookmark-star"></i>
                                    <h5 className="sidebar-list-font">Bookmarks</h5>
                                </li>
                                <hr style={{ color: '#0a0a0a' }}></hr>
                            </a>
                            <a className="cursor-pointer text-decoration-none">
                                <li className="d-flex flex-row sidebar-item sidebar-list-font">
                                    <i className="mx-2 bi bi-bookmarks"></i>
                                    <h5 className="sidebar-list-font">Collections</h5>
                                </li>
                                <hr style={{ color: '#0a0a0a' }}></hr>
                            </a>
                            <a className="cursor-pointer text-decoration-none">
                                <li className="d-flex flex-row sidebar-item sidebar-list-font">
                                    <i className="mx-2 bi bi-calendar-check"></i>
                                    <h5 className="sidebar-list-font">Events</h5>
                                </li>
                                <hr style={{ color: '#0a0a0a' }}></hr>
                            </a>
                            <a className="cursor-pointer text-decoration-none">
                                <li className="d-flex flex-row sidebar-item sidebar-list-font">
                                    <i className="mx-2 bi bi-clock-history"></i>
                                    <h5 className="sidebar-list-font">Order History</h5>
                                </li>
                                <hr style={{ color: '#0a0a0a' }}></hr>
                            </a>
                        </ul>
                    </div>
                    <div className="d-flex flex-column flex-lg-row w-100-md w-75-lg p-3 p-lg-0 m-l-4 pt-lg-3 pt-xl-4">
                        <div className="activity m-l-3">
                            <h3 className="heading-red">Notifications</h3>
                            <p className="font-14">No new friend requests or compliments at this time.</p>
                            <hr className="d-none d-lg-block" style={{ color: '#0a0a0a' }}></hr>
                            <h3 className="heading-red">Recent Activity</h3>
                            {<ActivityFeed />}
                            {<Post />}
                        </div>
                        <hr className="d-lg-none" style={{ color: '#0a0a0a' }}></hr>
                        <div className="grey-line-break ml-3">
                            <h3 className="heading-red mb-1 break-word">About
                                {
                                    currentUser ?
                                        <h3
                                            data-tip={currentUser.displayName}
                                            className="heading-red mb-1">
                                            {sliceDisplayName(currentUser)}
                                            <span><ReactTooltip place="top" type="dark" effect="float" /></span>
                                        </h3>
                                        :
                                        <h3 className="heading-red mb-1">No User</h3>
                                }
                            </h3>
                            <h5 className="about-subHeading mt-2">Yelping Since</h5>
                            <p className="font-14">Some month</p>
                            <h5 className="about-subHeading mt-2">Things I Love</h5>
                            <p className="font-14">You haven't said yet...</p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    );
};

export default Profile;

**編輯**
更新上傳任務
import { createUserProfileDocument } from "../../Utilities/Firebase/Firebase.utils";

    () => {
        storage
            .ref('images/')
            .child(image.name)
            .getDownloadURL(uploadTask.snapshot.ref)
            .then(async (url, firestore, userAuth) => {
                setUrl(url);
                const userRef = firestore.doc(`users/${userAuth.uid}`)
                await userRef.update({
                    photoURL: url
                });
                console.log('File available at', url);
            })
    }

更新後錯誤:
未處理的拒絕(類型錯誤 ):無法讀取未定義的屬性(讀取“文檔”)

**編輯更新 #2**
在 Frank van Puffelen 的幫助下,我似乎設法將上傳的照片從存儲中獲取到 Firestore 數據庫中。我可以在 photoURL 中當前用戶的 console.log 中看到它,並且它也顯示在 firebase db 用戶集合中。但是,如果我刷新或轉到另一個頁面,圖像就會消失,即使刷新後它仍然在 currentUser console.log 中顯示 URL。為什麼會發生這種情況?這一定是因為 setUrl(url) 在每次渲染時將 url 圖像的狀態重新初始化為空。我應該把這一切都扔掉,直接從 currentUser 調用圖像 url,如: currentUser.photoURL

更新代碼:
import { storage, firestore } from "../../Utilities/Firebase/Firebase.utils";

    () => {
        storage
            .ref('images/')
            .child(image.name)
            .getDownloadURL(uploadTask.snapshot.ref)
            .then(async (url) => {
                setUrl(url);
                const userRef = firestore.doc(`users/${currentUser.id}`)
                await userRef.update({
                    photoURL: url
                });
                console.log('File available at', url);
            })
    }
弗蘭克·範·普費倫

據我所知,您上傳圖像並在以下代碼段中獲取其下載 URL:

storage
    .ref("images")
    .child(image.name)
    .getDownloadURL(uploadTask.snapshot.ref)
    .then(url => {
        setUrl(url);
        console.log('File available at', url);
    })

要將新 URL 寫入 Firestore 中用戶的個人資料文檔,請將其添加到then()回調中:

const userRef = firestore.doc(`users/${userAuth.uid}`)
await userRef.update({
    photoURL: url
});

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何從雲函數將圖像存儲在 Firebase 存儲上

使用 Laravel 8 將圖像上傳到存儲和數據庫時出現的問題

調整圖像大小然後將其存儲在數據庫燒瓶中

如何從 Firebase Firestore 獲取數據並將其存儲在 List 中以在 Flutter Widgets 中使用?

將圖像同時上傳到 firebase 存儲和文本輸入到 firestore 時出錯

如何避免使用 django rest 框架將數據存儲在數據庫中

如何將數據上傳到壓縮圖像中?

如何使用自動映射器將傳入數據存儲到數據庫

將帶有一些其他數據的多張圖像存儲到 mongoDB 中時,只存儲一張圖像

使用 Laravel 中的控制器將數據從數據庫傳遞到刀片視圖

如何使用數據工廠將數據從 Azure Blob 存儲增量加載到 Azure SQL 數據庫?

如何從 reactJS 中的 firebase 存儲桶文件夾查看所有圖像

如何使用地圖將數據插入到我的 Firebase 數據庫中?

如何將數據從對像傳遞到javascript中的新數組?

您可以使用 vb.net 在您的 firebase 數據庫中存儲圖片嗎?

如何將數據從 expessjs 中間件傳遞到視圖,

邏輯應用程序 - 從 Web 服務讀取 XML 響應並將解析的數據存儲在數據庫中

如何使用azure數據工廠將數據從azure SQL數據庫增量存儲到azure blob存儲,基於一些條件:日期需要更新

如何將 List<Double> 保存到 Room 數據庫?

將 JPA @Enumerated 值保存到數據庫中

如何從 Aws s3 獲取圖像 url 位置並將其存儲在 mongodb 中

如何模擬存儲庫,使其不會從數據庫插入或提取數據

如何將數據從數據庫傳遞到Mailable?

如何在 Laravel 中將多個複選框值存儲到數據庫?

存儲後如何從片段中的視圖模型中重複調用數據?

從 ReactJS 上傳圖片到 Firebase v9 存儲

處於持久狀態的對像不會保存到數據庫中,而是從數據庫中成功加載

當我們將數據從加密的 AWS S3 存儲桶發送到加密的 Google Cloud Storage 存儲桶時,該數據在傳輸過程中是否加密?

如何在房間數據庫中存儲嵌套的json數據,kotlin