React上传Base64图片至MongoDB时偶现photo字段为false
React转Base64图片上传MongoDB偶现photo字段为"false"的问题
开发网站时,通过React将图片转换为Base64格式后上传至后端并存入MongoDB数据库,偶发异常:从数据库取回图片数据时,部分记录的photo字段值为"false",无法正常显示,其他记录的Base64图片数据正常,重新上传该图片有时可恢复正常。
问题示例数据
(3) [{…}, {…}, {…}] 0: photo: "false" __v: 0 _id: "650ce3fb077e8bd7795561e0" [[Prototype]]: Object 1: photo: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAA..." __v: 0 _id: "650ce411077e8bd7795561e4" [[Prototype]]: Object 2: photo: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAA..." __v: 0 _id: "650ce413077e8bd7795561e6" [[Prototype]]: Object length: 3
后端uploadImage路由代码
import express from 'express'; import * as dotenv from 'dotenv'; import Image from '../mongodb/models/image.js'; dotenv.config(); const router = express.Router(); router.route('/').get(async (req, res) => { try { await Image.find({}).then(data => { res.status(200).json({ success: true, data: data }); }); } catch (err) { console.log(err) res.status(500).json({ success: false, message: 'Fetching posts failed, please try again' }); } }); router.route('/').post(async (req, res) => { try { const { base64 } = req.body; await Image.create({ photo: base64, }); res.status(200).json({ success: true}); } catch (err) { console.log(err) res.status(500).json({ success: false, message: 'Unable to upload the image, please try again' }); } }); export default router;
React端上传图片代码
const handleImageUpload = async (e) => { const file = e.target.files[0]; var reader = new FileReader(); reader.readAsDataURL(file) reader.onload = () => { // base 64 // console.log(reader.result) SetImage(reader.result) } reader.onerror = e => { console.log("Reader Error " , e) } if (file) { const imageUrl = URL.createObjectURL(file); setForm({ ...form, file, photo: imageUrl }); try { const response = await fetch('http://localhost:8080/api/v1/uploadImage', { method: 'POST', headers: { "Content-Type": "application/json", Accept : "application/json", "Access-Control-Allow-Origin": "*", }, body: JSON.stringify({ base64 : image }), }); console.log(response); if (response.ok) { console.log('Image uploaded and saved successfully!'); } else { console.error('Failed to upload image'); } } catch (error) { console.error('Error uploading image:', error); } }; }
问题原因
FileReader.readAsDataURL是异步操作,你在调用fetch上传时,image状态可能还未完成更新(SetImage也是异步的),此时上传的base64参数可能是初始值(比如初始为false),导致后端存入数据库的photo字段为字符串"false"。
解决方法
将上传逻辑移至reader.onload回调内,确保拿到正确的Base64数据后再发起请求:
const handleImageUpload = async (e) => { const file = e.target.files[0]; if (!file) return; const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = async () => { const base64Data = reader.result; SetImage(base64Data); const imageUrl = URL.createObjectURL(file); setForm({ ...form, file, photo: imageUrl }); try { const response = await fetch('http://localhost:8080/api/v1/uploadImage', { method: 'POST', headers: { "Content-Type": "application/json", Accept: "application/json", }, body: JSON.stringify({ base64: base64Data // 直接使用reader.result,不依赖状态更新 }), }); console.log(response); if (response.ok) { console.log('Image uploaded and saved successfully!'); } else { console.error('Failed to upload image'); } } catch (error) { console.error('Error uploading image:', error); } }; reader.onerror = (err) => { console.log("Reader Error ", err); }; };
额外优化建议
- 后端增加参数校验:判断
base64是否以data:image/开头,不符合则返回错误,避免存入无效数据。 - 移除请求头中的
"Access-Control-Allow-Origin": "*",该字段是后端设置的响应头,前端请求添加无意义。
内容的提问来源于stack exchange,提问作者Nutrino DAYA
相关产品推荐
相关产品推荐

