如何从MongoDB获取二进制图片并在React JS中显示
解决MongoDB存储的二进制图片在React中无法显示的问题
图片已以二进制形式存储至MongoDB,但在React网页中无法显示,name、experience等其他属性可正常获取。以下是后端index.js及前端chattherapist.js的相关代码,需修复图片显示问题:
后端代码(index.js)
import express from "express" import cors from "cors" import mongoose from "mongoose" import multer from "multer" const app = express() app.use(express.json()) app.use(cors()) app.use(express.urlencoded({ extended: true })); mongoose.set("strictQuery", false) mongoose.connect("mongodb://127.0.0.1:27017/prj1", { useNewUrlParser: true, useUnifiedTopology: true }, () => { console.log("Connected !") }) const TherSchema = new mongoose.Schema({ name: String, spec: String, experience: String, qualification: String, photo: { data: Buffer, contentType: String } }) const Therapist1 = new mongoose.model("Therapist1", TherSchema) const upload = multer(); //adding therapist data in mongodb app.post('/therapist', upload.single('photo'), (req, res) => { const { name, spec, experience, qualification } = req.body; const therapist = new Therapist1({ name: name, spec: spec, experience: experience, qualification: qualification, photo: { data: req.file.buffer, contentType: req.file.mimetype } }); therapist.save(err => { if (err) { res.send(err); } else { res.send({ message: 'Therapist added!' }); } }); }); //fetching data from mongodb app.get("/chattherapdisplay", (req, res) => { Therapist1.find((err, data) => { if (err) { res.status(500).send(err); } else { res.status(200).send(data); } }); }); app.listen(9000, () => { console.log("Started at port 9000") })
前端代码(chattherapist.js)
import React, { useState, useEffect } from "react" import "./customer.css" import axios from "axios" const ChatTherapistdisplay = () => { const [therapist, setTherapist] = useState([]); useEffect(() => { const fetchdata = async () => { const data = await axios.get("http://localhost:9000/chattherapdisplay"); setTherapist(data.data); }; fetchdata(); }, []); return ( <div className="maincrd"> {therapist.map((therapist) => ( <div className="crd1" key={therapist._id}> Name: {therapist.name} <br /> Specialization: {therapist.spec} <br /> Qualification: {therapist.qualification} <br /> Experience: {therapist.experience} <br /> Photo: {therapist.photo && ( <img src={`data:${therapist.photo.contentType};base64,${btoa( new Uint8Array(therapist.photo.data).reduce( (data, byte) => data + String.fromCharCode(byte), '' ) )}`} alt="therapist" /> )} <br /> <div className="bkapp"> <a href="#">Book Appointment</a> </div> </div> ))} </div> ); } export default ChatTherapistdisplay
解决方案
方案一:修改前端图片转换逻辑
当前前端用btoa直接转换二进制数组时,可能因字符编码问题导致失效,可改用更可靠的Base64转换方式:
替换前端图片部分的代码:
{therapist.photo && ( <img src={`data:${therapist.photo.contentType};base64,${Buffer.from(therapist.photo.data).toString('base64')}`} alt="therapist" /> )}
若浏览器不支持Buffer,可使用兼容方法:
function arrayToBase64(buffer) { let binary = ''; const bytes = new Uint8Array(buffer); for (let i = 0; i < bytes.byteLength; i++) { binary += String.fromCharCode(bytes[i]); } return btoa(binary); } // 图片标签中调用该方法 {therapist.photo && ( <img src={`data:${therapist.photo.contentType};base64,${arrayToBase64(therapist.photo.data)}`} alt="therapist" /> )}
方案二:后端新增单独图片接口(推荐)
这种方式更符合RESTful设计,避免前端处理大量二进制数据:
- 在后端
index.js中新增接口:
// 根据ID获取 therapist 图片 app.get('/therapist/photo/:id', (req, res) => { Therapist1.findById(req.params.id, (err, therapist) => { if (err) { res.status(500).send(err); } else { res.set('Content-Type', therapist.photo.contentType); res.send(therapist.photo.data); } }); });
- 修改前端图片部分代码,直接引用接口URL:
{therapist.photo && ( <img src={`http://localhost:9000/therapist/photo/${therapist._id}`} alt="therapist" /> )}
内容的提问来源于stack exchange,提问作者Curious_Mind
相关产品推荐
相关产品推荐

