我目前正在开发一个项目,后端使用 Express.js,前端使用 React。该项目涉及将图像上传到 Cloudinary,然后将 Cloudinary URL 保存在 MongoDB 数据库中。但是,我遇到了一个问题,即存储在数据库中的 Cloudinary URL 开头包含“未定义”字符串。
问题描述:
这是我的项目中的步骤顺序:
前端:我选择要上传的图像,并使用 Cloudinary API 正确获取了该图像的 Cloudinary URL。
后端(Express.js):我将 Cloudinary URL 从前端发送到服务器并将其存储在 MongoDB 数据库中。
但是,当我稍后从数据库检索 Cloudinary URL 时,它显示为 “undefined”后跟实际的 Cloudinary URL (例如:“未定义http://res.cloudinary.com/...”)。
后端:
// Back-end code for handling image upload
const express = require('express');
const router = express.Router();
const cloudinary = require('../utils/cloudinary');
//upload
const upload = multer({ dest: 'uploads' });
// ... (other imports and middleware)
// POST /upload/image
// Upload product images
// Protected route (isAuth middleware checks authentication)
router.post('/image', isAuth, upload.single('image'), async (req, res) => {
try {
const file = req.file.path;
// Upload the image to Cloudinary
const result = await cloudinary.uploader.upload(file);
// Check if the image was successfully uploaded to Cloudinary
if (!result || !result.url) {
return res.status(500).json({ errors: { msg: 'Image upload failed' } });
}
// If the image was uploaded successfully, save the Cloudinary URL in the database
const imagePath = result.url;
// ... (other code for saving imagePath to MongoDB)
res.status(200).json({ imagePath });
} catch (error) {
console.error(error);
res.status(500).json({ errors: { msg: 'Server error' } });
}
});
// ... (other routes)
前端
const [form, setForm] = useState({
productName: '',
description: '',
basePrice: 0,
duration: 300,
category: '',
image: '',
});
const [file, setFile] = useState('');
const [fileName, setFileName] = useState('Choose your image file...');
const [fileValid, setFileValid] = useState(true);
const [uploading, setUploading] = useState(false);
let navigate = useNavigate();
useEffect(() => {
return () => {
props.clearAlerts();
};
}, []);
const handleFormChange = (e) => {
e.preventDefault();
setForm({
...form,
[e.target.name]: e.target.value,
});
};
const handleSubmit = async (e) => {
e.preventDefault();
// Check for empty fields
if (form.productName === '') {
return props.setAlert('Product name required!');
}
if (form.basePrice.toString() === '0') {
return props.setAlert('Base price required!');
}
if (form.duration.toString() === '0') {
setForm({ ...form, duration: 300 });
}
if (!fileValid) {
// if selected file is not image/exceeds size limit
props.setAlert('Image file not valid!', 'error');
} else {
if (file === '') {
// submit without photo
await props.postAd(form);
navigate('/');
} else {
// with photo
const imagePath = await uploadImage();
console.log(imagePath);
if (imagePath) {
await props.postAd({ ...form, image: imagePath });
navigate('/');
}
}
}
};
const fileSelected = (e) => {
let filesize = (e.target.files[0].size / (1024 * 1024)).toFixed(3);
let fileType = e.target.files[0].type.toString();
let regex = /^image\/(png|jpg|jpeg|gif)$/;
// if (fileType !== 'image/jpeg' && fileType !== 'image/png') {
if (!regex.test(fileType)) {
props.setAlert('Image must be of type JPEG, PNG or GIF');
setFile('');
setFileValid(false);
} else if (filesize > 3) {
props.setAlert('Image size must be less than 3 MB', 'error');
setFile('');
setFileValid(false);
} else {
setFileValid(true);
setFile(e.target.files[0]);
setFileName(e.target.files[0].name);
console.log(e.target.files[0]);
}
};
const uploadImage = async () => {
setUploading(true);
const formData = new FormData();
formData.append('image', file);
console.log(file)
console.log(formData)
try {
const res = await axios.post(
`${process.env.REACT_APP_API_BASE_URL}/upload/image`,
formData,
{ headers: { 'Content-Type': 'multipart/form-data' } }
);
console.log(res.data)
return res.data.imagePath;
} catch (error) {
console.log(error);
setUploading(false);
props.setAlert('File upload failed', 'error');
}
};
背景:
处理图像上传到Cloudinary并保存URL的代码 MongoDB 似乎按预期运行,但问题 稍后从数据库检索 URL 时会出现。
imagePath 变量已正确填充 Cloudinary URL 在将其保存到数据库之前,并且在保存时没有问题 图片上传后发送URL到前端。
这可能源于您上传图像后在前端处理响应的方式。你能尝试像这样添加验证吗?
try {
const res = await axios.post(
`${process.env.REACT_APP_API_BASE_URL}/upload/image`,
formData,
{ headers: { 'Content-Type': 'multipart/form-data' } }
);
if (res.data && typeof res.data.imagePath === 'string') {
return res.data.imagePath;
} else {
return 'Default URL or handle the error';
}
}