MongoDB 如何在 ReactJS 中显示图像

How to display image in ReactJS from MongoDB

我目前正在使用 React、Node 和 MongoDB 构建绘图应用程序。

它将图像连同名称和用户名一起保存在数据库中。打开主页时,它必须检索图像并将其显示在屏幕上。

图像以缓冲区的形式存储在数据库中,在屏幕上显示时,我正在将其转换为 base64(在某篇文章中找到)。

当我出于测试目的尝试在 node_app 中的 imagesPage.ejs 中显示它时,它可以正确显示图像,但是当我尝试在 React 组件中显示它时,它给出了以下错误:

GET data:image/{image.img.contentType};base64,$(data.img.data.toString('base64')) net::ERR_INVALID_URL

当我通过删除 {image.img.contentType} 之前的额外“图像/”来更改图像 url 时,我收到此错误:

Failed to load resource: net::ERR_INVALID_URL

react_app 部分:

我正在 CardData.js 中获取数据,并且在我使用 console.log 验证时正确获取数据:

import React, { useState } from "react";
import Axios from "axios";

export default function CardData(){
    const [data, setData] = useState({
        lst: []
    });

    const url = `http://localhost:5000/getDrawings/${localStorage.getItem("user")}`;
    Axios.get(url).then((res)=>{
        setData(res.data);
    }).catch(err=>console.log(err));

    return data;
} 

Card.js 显示图像(使用 try...catch 显示剩余页面,即使图像有错误):

import React, { useEffect, useState } from "react";
import CardData from "./CardData";

function Card(){
    
    const cards = CardData();
    try{const allCards = cards.map( function (data) {
        //let username = data.username;
        console.log("here!!!");
        let name = data.name;
        let image = `data:{image.img.contentType};base64,$(data.img.data.toString('base64'))`;

        return( 
            <div className = "col-3">
                <div className = "adjust">
                    <div className="image">
                        <img width="300" height="300" src={image}></img>
                    </div>
                    <div className="name">{name}</div>
                </div>
            </div>
        );
    })
    return [allCards];}
    catch(e){ return null;}
}

export default Card;

node_app 部分:

imageModel.js 包含猫鼬模式:

const Mongoose = require('mongoose')

const imageSchema = Mongoose.Schema({
    name: {
        type: String,
        default: ""
    },
    username: {
        type: String,
        default: ""
    },
    img:
    {
        data: Buffer,
        contentType: {
            type: String,
            default: 'image/png'
        }
    }
}); 

module.exports = Mongoose.model('Image',imageSchema);

router.js 包含路线 :

const express = require('express')
const router = express.Router()
//const imgModel = require('../models/imageModel')
const { 
        // other components.
        getDrawings,
} = require('../controllers/controllers')
const imgModel = require('../models/imageModel');

//other router.post and router.get
router.get('/getDrawings/:username',getDrawings);

module.exports = router;

controllers.js 包含 getDrawings 函数:

//all necessary imports

const getDrawings = async (req, res) => {
    const username = req.params.username;
    const items = await imgModel.find({username : username});

    //to display imagesPage.ejs I uncomment this and comment out res.send(items)
    //res.render('imagesPage',{items : items});

    res.send(items); 
}

//also exports other functions but removed it from here.
module.exports = {getDrawings};

imagesPage.ejs 正确显示图像(它也用于将图像添加到数据库,但这不是我当前的问题):


<!DOCTYPE html>
<html lang="en">
  
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Image Uploading</title>
</head>
  
<body>
 
    <h1>Uploaded Images</h1>
    <div>
        <% items.forEach(function(image) { %>
        <div>
            <div>
                <img src="data:image/<%=image.img.contentType%>;base64,
                     <%=image.img.data.toString('base64')%>" style="width:300px;height: 300px">
                <div>
                    <h5><%= image.name %></h5>
                </div>
            </div>
        </div>
        <% }) %>
    </div>
</body>
  
</html>

反应页面正确显示图像名称和剩余页面但不显示图像并给出上述错误,而 imagesPage.ejs 正确显示所有内容。 请帮帮我。

谢谢:)

在以下赋值中传入变量时:

let image = `data:{image.img.contentType};base64,$(data.img.data.toString('base64'))`;

您必须使用 ${ } 而不是 $( )

let image = `data:${image.img.contentType};base64,${data.img.data.toString('base64')}`;

假设 image.img.contentType 也是该范围内的一个变量

因此,由于服务器正在发送 JSON 图像,您需要使用 Int8Array

将 JSON 转换为 Buffer

然后就是需要转成Blob,然后创建一个URL对象:

编辑:获取时使用 useEffect,这就是导致循环错误的原因

立即尝试:

import React, { useState, useEffect } from "react";
import Axios from "axios";

export default function CardData(){
    const [data, setData] = useState(
        []
    );


useEffect(() => {

    const url = `http://localhost:5000/getDrawings/${localStorage.getItem("user")}`;
    Axios.get(url).then((res)=>{
        setData(res.data);
    }).catch(err=>console.log(err));
  }, []);

    return data;
} 
import React, { useEffect, useState } from "react";
import CardData from "./CardData";

function Card(){
    
    const cards = CardData();
    try{const allCards = cards.map( function (data) {
        //let username = data.username;
        console.log("here!!!");
        const name = data.name;

        const blob = new Blob([Int8Array.from(data.img.data.data)], {type: data.img.contentType });

        const image = window.URL.createObjectURL(blob);

        return( 
            <div className = "col-3">
                <div className = "adjust">
                    <div className="image">
                        <img width="300" height="300" src={image}></img>
                    </div>
                    <div className="name">{name}</div>
                </div>
            </div>
        );
    })
    return [allCards];}
    catch(e){ return null;}
}

export default Card;