材质UI头像图片上传
Posted
技术标签:
【中文标题】材质UI头像图片上传【英文标题】:Material UI Avatar Image Upload 【发布时间】:2021-11-10 12:16:21 【问题描述】:我设法制作了头像选择器,但我不知道如何在 Firebase 中保存图片,甚至不知道如何将其保存为个人资料图片。
看起来是这样的:
如果我点击按钮就会出现:
我可以选择一张图片,但它不会保存在任何地方,也不会在头像中显示图片。 我的代码:
function Profile(props, navigation)
const classes = useStyles();
const user = useUser(props.route.params.uid);
const [time, setTime] = useState("7:30");
const [timing, setTiming] = useState([]);
const [timeAfternoon, setTimeAfternoon] = useState("7:30");
const [timingAfternoon, setTimingAfternoon] = useState([]);
const [sickDaysStart, setSickDaysStart] = useState(Date.now());
const [sickDaysEnd, setSickDaysEnd] = useState(Date.now());
const [sickDaysConfirm, setSickDaysConfirm] = useState([]);
const [donwloadURL, setDownloadURL] = useState([]);
const onLogout = () =>
firebase.auth().signOut();
;
function handelSickDaysStart(e)
setSickDaysStart(e.target.value);
function handelSickDaysEnd(e)
setSickDaysEnd(e.target.value);
function handleTime(e)
setTime(e.target.value);
function handleTimeAfternoon(e)
setTimeAfternoon(e.target.value);
function delayMorning()
db.collection("delayInTheMorning")
.doc()
.set(
time,
user,
)
.then(() =>
//If you wish to push the written data to your local state, you can do it here
setTiming([...timing, time ]);
console.log("Documents saved succesfully");
)
.catch((err) =>
console.log(err);
);
function delayAfternoon()
db.collection("delayInTheAfternoon")
.doc()
.set(
timeAfternoon,
)
.then(() =>
//If you wish to push the written data to your local state, you can do it here
setTimingAfternoon([...timingAfternoon, timeAfternoon ]);
console.log("Documents saved succesfully");
)
.catch((err) =>
console.log(err);
);
function sickDaysStartEnd()
db.collection("DaysofSickness")
.doc()
.set(
sickDaysStart,
sickDaysEnd,
user,
)
.then(() =>
//If you wish to push the written data to your local state, you can do it here
setSickDaysConfirm([
...sickDaysConfirm,
sickDaysStart, sickDaysEnd ,
]);
console.log("Documents saved succesfully");
)
.catch((err) =>
console.log(err);
);
function isCurrentUserProfile()
if (props.route.params.uid === firebase.auth().currentUser.uid)
return true;
else
return false;
async function handleFileInputChange(e)
const files = e.target.files;
const file = files[0];
const storage = firebase.storage();
const usersImageRef = storage
.ref()
.child(`users/$user.uid/profilepicture.jpg`);
const snap = await usersImageRef.put(file);
const donwloadURL = await snap.ref.getDownloadURL();
setDownloadURL(donwloadURL);
await firebase.auth().currentUser.updateProfile( photoURL: donwloadURL );
if (user === null)
return <div className=classes.root />;
return (
<ScrollView style=styles.root>
<Container className=classes.div>
<input
accept="image/*"
className=classes.input
id="contained-button-file"
multiple
type="file"
onChange=handleFileInputChange
/>
<label>
<IconButton>
<Avatar
src="../assets/ana.png"
style=
margin: "10px",
width: "60px",
height: "60px",
/>
</IconButton>
</label>
<Typography className=classes.text> user.name </Typography>
<Typography className=classes.text> user.email </Typography>
isCurrentUserProfile() ? (
<Button
className=classes.btn
size="large"
variant="outlined"
onClick=() => onLogout()
>
Logout
</Button>
) : null
</Container>
<Card className=classes.div>
/* //Verspätung */
<CardContent className=classes.cardBackGround>
<Typography variant="h5" className=classes.cardTyp>
" "
Verspätung" "
</Typography>
<Container className=classes.cardContainer>
<TextField
id="time"
label="Zeit"
type="time"
defaultValue="07:30"
InputLabelProps=
shrink: true,
inputProps=
step: 300, // 5 min
onChange=(value) =>
handleTime(value);
/>
<Button className=classes.cardBtn onClick=() => delayMorning()>
Absenden
</Button>
</Container>
</CardContent>
/* //Krankenmledungen */
<CardContent className=classes.cardBackGround>
<Typography variant="h5" className=classes.cardTyp>
Krankenmledungen
</Typography>
<Container className=classes.cardContainer>
<TextField
id="date"
label="Von"
type="date"
defaultValue="2021-09-14"
className=classes.textField
InputLabelProps=
shrink: true,
onChange=(value) =>
handelSickDaysStart(value);
/>
<TextField
id="date"
label="bis"
type="date"
defaultValue="2021-09-20"
className=classes.textField
InputLabelProps=
shrink: true,
onChange=(value) =>
handelSickDaysEnd(value);
/>
</Container>
<Button
className=classes.cardBtnKM
onClick=() => sickDaysStartEnd()
>
Absenden
</Button>
</CardContent>
/* //Verspätung Abolung*/
<CardContent className=classes.cardBackGround>
<Typography variant="h5" className=classes.cardTyp>
" "
Verspätung Abholung
</Typography>
<Container className=classes.cardContainer>
<TextField
id="time"
label="Zeit"
type="time"
defaultValue="07:30"
InputLabelProps=
shrink: true,
inputProps=
step: 300, // 5 min
onChange=(value) =>
handleTimeAfternoon(value);
/>
<Button
className=classes.cardBtn
onClick=() => delayAfternoon()
>
Absenden
</Button>
</Container>
</CardContent>
</Card>
/* <List> */
/* Verspätungs Liste */
timing.map((item) =>
return (
<List className=classes.lists>
<ListItem className=classes.list1>
<ListItemAvatar>
<Avatar></Avatar>
</ListItemAvatar>
<ListItemText
primary=user.name
secondary=`Verspätung in der Früh $item.time`
/>
</ListItem>
</List>
);
)
/* Krankmeldung */
timingAfternoon.map((item) =>
return (
<List className=classes.lists>
<ListItem className=classes.list>
<ListItemAvatar>
<Avatar></Avatar>
</ListItemAvatar>
<ListItemText
primary=user.name
secondary=`Verspätung bei der Abholung $item.timeAfternoon`
/>
</ListItem>
</List>
);
)
/* Verspätungs Nachmittag */
sickDaysConfirm.map((item) =>
return (
<List className=classes.lists>
<ListItem className=classes.list>
<ListItemAvatar>
<Avatar></Avatar>
</ListItemAvatar>
<ListItemText
primary=user.name
secondary=`Krankmeldung von $item.sickDaysStart bis $item.sickDaysEnd`
/>
</ListItem>
</List>
);
)
</ScrollView>
);
还有一个来自 Expo 的 imagePicker,我想尝试一下,但我不确定。
【问题讨论】:
【参考方案1】:如果您想更改用户的个人资料图片,可以使用此代码:
import getAuth, updateProfile from "firebase/auth";
const auth = getAuth();
updateProfile(auth.currentUser,
displayName: "User Name", photoURL: "https://example.com/jane-q-user/profile.jpg"
).then(() =>
// Profile updated!
// ...
).catch((error) =>
// An error occurred
// ...
);
你可以找到更多关于它的信息here。
要获取图片 URL,您需要将其上传到 Firebase 存储并获取 downloadURL
:
import getStorage, ref, uploadBytes, getDownloadURL from "firebase/storage";
const storage = getStorage();
const storageRef = ref(storage, 'some-child');
// 'file' comes from the Blob or File API
uploadBytes(storageRef, file).then((snapshot) =>
console.log('Uploaded a blob or file!');
getDownloadURL(snapshot.ref).then((downloadURL) =>
console.log('File available at', downloadURL);
);
);
我还将input
更改为没有multiple
文件可供选择。如果您愿意分享更多代码,我可以将这些代码 sn-ps 集成到您的代码中,以防您遇到问题。
更新:
这是整个示例。我看到你使用旧的 SDK,所以例子就是它:
function Profile(props, navigation)
const classes = useStyles();
const user = useUser(props.route.params.uid);
const delay = DayandTime();
const [time, setTime] = useState("7:30");
const [timing, setTiming] = useState([]);
const [downloadurl, setDU] = useState("/images/example.jpg");
const [timeAfternoon, setTimeAfternoon] = useState("7:30");
const [timingAfternoon, setTimingAfternoon] = useState([]);
const [sickDaysStart, setSickDaysStart] = useState(Date.now());
const [sickDaysEnd, setSickDaysEnd] = useState(Date.now());
const [sickDaysConfirm, setSickDaysConfirm] = useState([]);
const onLogout = () =>
firebase.auth().signOut();
;
function handelSickDaysStart(e)
setSickDaysStart(e.target.value);
function handelSickDaysEnd(e)
setSickDaysEnd(e.target.value);
function handleTime(e)
setTime(e.target.value);
function handleTimeAfternoon(e)
setTimeAfternoon(e.target.value);
function delayMorning()
db.collection("delayInTheMorning")
.doc()
.set(
time,
user,
)
.then(() =>
//If you wish to push the written data to your local state, you can do it here
setTiming([...timing, time ]);
console.log("Documents saved succesfully");
)
.catch((err) =>
console.log(err);
);
function delayAfternoon()
db.collection("delayInTheAfternoon")
.doc()
.set(
timeAfternoon,
)
.then(() =>
//If you wish to push the written data to your local state, you can do it here
setTimingAfternoon([...timingAfternoon, timeAfternoon ]);
console.log("Documents saved succesfully");
)
.catch((err) =>
console.log(err);
);
function sickDaysStartEnd()
db.collection("DaysofSickness")
.doc()
.set(
sickDaysStart,
sickDaysEnd,
user,
)
.then(() =>
//If you wish to push the written data to your local state, you can do it here
setSickDaysConfirm([
...sickDaysConfirm,
sickDaysStart, sickDaysEnd ,
]);
console.log("Documents saved succesfully");
)
.catch((err) =>
console.log(err);
);
function isCurrentUserProfile()
if (props.route.params.uid === firebase.auth().currentUser.uid)
return true;
else
return false;
if (user === null)
return <div className=classes.root />;
async function handleFileInputChange(e)
const files = e.target.files;
const file = files[0];
const storage = firebase.storage();
const usersImageRef = storage
.ref()
.child(`users/$user.uid/profilepicture.jpg`);
const snap = await usersImageRef.put(file);
const downloadURL = await snap.ref.getDownloadURL();
setDU(downloadURL);
await firebase.auth().updateProfile( photoURL: downloadURL );
return (
<ScrollView style=styles.root>
<Container className=classes.div>
<input
accept="image/*"
className=classes.input
id="contained-button-file"
multiple
type="file"
onChange=handleFileInputChange
/>
<label htmlFor="contained-button-file">
<IconButton>
<Avatar
src="/images/example.jpg"
style=
margin: "10px",
width: "60px",
height: "60px",
/>
</IconButton>
</label>
<Typography className=classes.text> user.name </Typography>
<Typography className=classes.text> user.email </Typography>
isCurrentUserProfile() ? (
<Button
className=classes.btn
size="large"
variant="outlined"
onClick=() => onLogout()
>
Logout
</Button>
) : null
</Container>
<Card className=classes.div>
/* //Verspätung */
<CardContent>
<Typography variant="h5" className=classes.cardTyp>
" "
Verspätung" "
</Typography>
<Container className=classes.cardContainer>
<TextField
id="time"
label="Zeit"
type="time"
defaultValue="07:30"
InputLabelProps=
shrink: true,
inputProps=
step: 300, // 5 min
onChange=(value) =>
handleTime(value);
/>
<Button className=classes.cardBtn onClick=() => delayMorning()>
Absenden
</Button>
</Container>
</CardContent>
/* //Krankenmledungen */
<CardContent className=classes.cardKrankmeldung>
<Typography variant="h5" className=classes.cardTyp>
" "
Krankenmledungen" "
</Typography>
<Container className=classes.cardContainer>
<TextField
id="date"
label="Von"
type="date"
defaultValue="2021-09-14"
className=classes.textField
InputLabelProps=
shrink: true,
onChange=(value) =>
handelSickDaysStart(value);
/>
<TextField
id="date"
label="bis"
type="date"
defaultValue="2021-09-20"
className=classes.textField
InputLabelProps=
shrink: true,
onChange=(value) =>
handelSickDaysEnd(value);
/>
</Container>
<Button
className=classes.cardBtnKM
onClick=() => sickDaysStartEnd()
>
Absenden
</Button>
</CardContent>
/* //Verspätung Abolung*/
<CardContent>
<Typography variant="h5" className=classes.cardTyp>
" "
Verspätung Abholung
</Typography>
<Container className=classes.cardContainer>
<TextField
id="time"
label="Zeit"
type="time"
defaultValue="07:30"
InputLabelProps=
shrink: true,
inputProps=
step: 300, // 5 min
onChange=(value) =>
handleTimeAfternoon(value);
/>
<Button
className=classes.cardBtn
onClick=() => delayAfternoon()
>
Absenden
</Button>
</Container>
</CardContent>
</Card>
<List>
/* Verspätungs Liste */
<ListItem>
<ListItemAvatar>
<Avatar></Avatar>
</ListItemAvatar>
<ListItemText
primary=user.name
secondary=`Verspätung in der Früh $delay`
/>
</ListItem>
/* Verspätungs Krankmeldung */
<ListItem>
<ListItemAvatar>
<Avatar></Avatar>
</ListItemAvatar>
<ListItemText
primary=user.name
secondary=`Krankmeldung $delay`
/>
</ListItem>
/* Verspätungs Nachmittag */
<ListItem>
<ListItemAvatar>
<Avatar></Avatar>
</ListItemAvatar>
<ListItemText
primary=user.name
secondary=`Verspätung Nachmittag $delay`
/>
</ListItem>
</List>
</ScrollView>
);
const mapStateToProps = (store) => (
currentUser: store.userState.currentUser,
posts: store.userState.posts,
following: store.userState.following,
);
export default connect(mapStateToProps, null)(Profile);
const useStyles = makeStyles(
root:
backgroundColor: "white",
,
div:
marginTop: 20,
marginLeft: 15,
marginRight: 15,
backgroundColor: "white",
,
avatar:
marginBottom: 10,
,
btn:
marginTop: 10,
width: 250,
marginBottom: 30,
,
text:
fontSize: 25,
marginTop: 10,
,
cardTyp:
textAlign: "left",
paddingLeft: 13,
,
cardBtn:
marginTop: 20,
marginLeft: 30,
,
cardBtnKM:
marginTop: 20,
marginLeft: 10,
,
cardContainer:
display: "flex",
,
);
const styles = StyleSheet.create(
root:
backgroundColor: "white",
,
);
【讨论】:
嘿@Tarik 谢谢!如果您能提供帮助,我会更新整个代码,因为我想我可以自己实现它,但我太不确定了。 我已经用整个代码更新了答案。 谢谢,但我收到一条错误消息:''Unhandled Rejection (TypeError): snap.getDownloadURL is not a function'' 我已经更新了代码。应该是snap.ref.get...
您好@Tarik,我尝试自己解决,但仍然出现错误:Profile.js:135 Uncaught (in promise) ReferenceError: setDownloadURL is not defined以上是关于材质UI头像图片上传的主要内容,如果未能解决你的问题,请参考以下文章