我有一个 MERN 堆栈应用程序,我将其部署到 Render(服务器端作为 Web 服务,前端作为静态)。
在我的应用程序中,我有一个配置文件,用户可以在其中上传头像图像。我将图像作为 URL 字符串存储在用户模型的 MongoDB Atlas_ 中。
图像保存在服务器上的上传文件夹中。图像上传工作正常,并且从部署和本地环境中成功获取图像。但过了一会儿,我在获取相同图像时开始出现内部服务器错误。
这个问题是什么原因以及如何解决?或者有没有更好的方法在 MongoDB Atlas 中存储图像而不使用云或GridFS?
这是我设置用户头像的方法:
const setUserAvatar = async (req, res) => {
try {
if (!req.user || !req.user.id) {
return res.status(401).json({ message: 'Unauthorized' });
}
const user = await User.findById(req.user.id);
if (!user) {
return res.status(404).json({ message: 'User not found' });
}
if (!req.file) {
return res.status(400).json({ message: 'No file uploaded' });
}
const fileName = `avatar_${user.id}_${Date.now()}.png`;
const filePath = path.join(__dirname, '..', 'uploads', fileName);
fs.writeFileSync(filePath, req.file.buffer);
user.avatar = { data: fileName };
await user.save();
res.status(200).json({ message: 'Avatar uploaded successfully' });
} catch (error) {
console.error('Error uploading avatar', error);
res.status(500).json({ message: 'Internal Server Error' });
}
};
并得到:
const getUserAvatar = async (req, res) => {
const userId = req.user.id;
try {
const user = await User.findById(userId);
if (user.avatar.data === null) {
return res.status(404).json({ message: 'No avatar found' })
}
if (!user || !user.avatar.data) {
res.send(user.avatar.data)
} else {
const filePath = path.join(__dirname, '..', 'uploads', user.avatar.data);
const avatarData = fs.readFileSync(filePath);
res.setHeader('Content-Type', 'image/*');
res.send(avatarData);
}
} catch (error) {
console.error('Error fetching avatar', error);
res.status(500).json({ message: 'Internal Server Error' });
}
};
前端如何处理头像变更:
const handleAvatarChange = async (e) => {
const token = localStorage.getItem('token');
if (token) {
try {
const formData = new FormData();
formData.append('avatar', e.target.files[0])
const response = await fetch('RENDERLINK/avatar', {
'method': 'POST',
'headers': {
'Authorization': `Bearer ${token}`,
},
'body': formData,
'credentials': 'include'
})
if (response.status === 200) {
getUser()
toast.success('Avatar changed successfully')
} else if (response.status === 400) {
toast.error('No file selected')
} else {
toast.error('Error changing avatar')
}
} catch (error) {
toast.error('Oops! Something went wrong. Please try again later.')
}
} else {
console.log('No token found')
navigate('/login')
}
}
获取包括头像在内的用户数据:
const getUser = async () => {
const token = localStorage.getItem('token');
if (token) {
try {
const response = await fetch('RENDERLINK/profile', {
'method': 'POST',
'headers': {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
'credentials': 'include'
})
if (response.ok) {
const data = await response.json();
setUser({ username: data.username, email: data.email, avatar: data.avatar.data })
if (data.avatar.data !== null) {
// Fetch and set the avatar image
const avatarResponse = await fetch('RENDERLINK/get_avatar', {
headers: {
'Authorization': `Bearer ${token}`,
},
credentials: 'include',
});
const avatarBlob = await avatarResponse.blob();
const avatarUrl = URL.createObjectURL(avatarBlob);
setUser((prevUser) => ({ ...prevUser, avatar: avatarUrl }));
setLoading(false)
}
} else if (response.status === 500) {
toast.error('Oops! Something went wrong. Please try again later.')
}
} catch (error) {
toast.error('Oops! Something went wrong. Please try again later.')
}
} else {
console.log('No token found')
navigate('/login')
}
}
在渲染中,您可以创建磁盘并将文件保存在项目文件夹之外。它解决了我的问题,因为现在当我需要将更新的代码推送到 GitHub 时,它不会影响用户上传的图像。