我正在尝试更新用户图像,名称和电子邮件,这是从后端工作完美,但当我从前端尝试更新只适用于名称和电子邮件,而不是图像,我不知道为什么…
代码如下:
前端
这里我发送一个请求来更新名称,电子邮件和图像
const userDataForm = document.querySelector('.profile-update');
if (userDataForm)
userDataForm.addEventListener('submit', async (e) => {
e.preventDefault();
const name = document.getElementById('nameInput').value;
const email = document.getElementById('emailInput').value;
const image = document.getElementById('profile-img-file-input').files[0];
try {
const res = await fetch('/api/v1/users/updateMe', {
method: 'PATCH',
body: JSON.stringify({ name, email, image }),
headers: { 'Content-Type': 'application/json' },
});
console.log(res);
const data = await res.json();
if (data.status == 'success') {
alert('success');
}
} catch (error) {
alert(error);
}
});
profile.ejs
这是ejs页面
<div class="profile-user position-relative d-inline-block mx-auto mb-4">
<img
src="/assets/img/<%= user.photo %>"
id="user-profile-image"
class="rounded-circle avatar-xl img-thumbnail user-profile-image"
alt="user-profile-image"
/>
<div class="avatar-xs p-0 rounded-circle profile-photo-edit">
<input
id="profile-img-file-input"
name="photo"
accept="image/*"
type="file"
class="profile-img-file-input"
/>
<label for="profile-img-file-input" class="profile-photo-edit avatar-xs">
<span class="avatar-title rounded-circle bg-light text-body">
<i class="ri-camera-fill"></i>
</span>
</label>
</div>
</div>
后端代码
这里是用来上传图片和更新名字email和图片的控制器
const multerStorage = multer.memoryStorage();
const multerFilter = (req, file, cb) => {
if (file.mimetype.startsWith('image')) {
cb(null, true);
} else {
cb(new AppError('not an image! please upload only images', 400), false);
}
};
// const upload = multer({ dest: 'public/img/users' });
const upload = multer({
storage: multerStorage,
fileFilter: multerFilter,
});
exports.uploadUserPhoto = upload.single('photo');
exports.resizeUserPhoto = catchAsync(async (req, res, next) => {
if (!req.file) return next();
req.file.filename = `user-${req.user.id}-${Date.now()}.jpeg`;
await sharp(req.file.buffer)
.resize(500, 500)
.toFormat('jpeg')
.jpeg({ quality: 90 })
.toFile(`public/assets/img/${req.file.filename}`);
next();
});
const filterObj = (obj, ...allowedFields) => {
const newObj = {};
Object.keys(obj).forEach((el) => {
if (allowedFields.includes(el)) newObj[el] = obj[el];
});
return newObj;
};
exports.updateMe = async (req, res, next) => {
// console.log('the filename', req.file);
// console.log(req.body);
// Create an error if a user POSTs password data
if (req.body.password || req.body.passwordConfirm) {
return next(new AppError('This route is not for password update Please use /updateMyPassword', 400));
}
// Update user document
// const user = await User.findById(req.user.id);
// Filterd out unwanted fields that are not allowed to be
// updated
const filteredBody = filterObj(req.body, 'name', 'email');
if (req.file) filteredBody.photo = req.file.filename;
// update the user
const updatedUser = await User.findByIdAndUpdate(req.user._id, filteredBody, {
new: true,
runValidators: true,
});
res.status(200).json({
status: 'success',
data: {
user: updatedUser,
},
});
};
这是路由文件
router.patch('/updateMe', userController.uploadUserPhoto, userController.resizeUserPhoto, userController.updateMe);
所以,解决方案是使用表单数据API,它允许我们发送多部分/表单数据(这有助于通过表单上传文件)
这篇文章也帮助了我https://blog.logrocket.com/multer-nodejs-express-upload-file/
const userDataForm = document.querySelector('.profile-update');
if (userDataForm)
userDataForm.addEventListener('submit', async (e) => {
e.preventDefault();
const form = new FormData();
console.log(form);
form.append('name', document.getElementById('nameInput').value);
form.append('email', document.getElementById('emailInput').value);
form.append('photo', document.getElementById('profile-img-file-input').files[0]);
console.log(form);
try {
const res = await fetch('/api/v1/users/updateMe', {
method: 'PATCH',
body: form,
});
console.log(res);
const data = await res.json();
console.log(data);
console.log(form);
if (data.status == 'success') {
showAlert('success', 'Profile successfully updated');
window.location.reload();
}
} catch (error) {
alert(error);
}
});