I am currently building a drawing app using React, Node and MongoDB.
It saves images along with name and username in the database. When home page is opened, it has to retrieve and display the image on the screen.
The image is stored in database in the form of a buffer and while displaying it on screen, I am converting it to base64 (found it in some article).
When I try to display it in imagesPage.ejs present inside the node_app for testing purpose, it is properly displaying the image but when I try to do it inside the react component, it is giving the following error:
GET data:image/{image.img.contentType};base64,$(data.img.data.toString('base64')) net::ERR_INVALID_URL
and when I change the image url by removing that extra "image/" before {image.img.contentType}, i get this error :
Failed to load resource: net::ERR_INVALID_URL
react_app part :
I am fetching data in CardData.js and it is fetching it correctly as I verified using 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 to display the image ( used try...catch to display remaining page even if there's an error with the image) :
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 part :
imageModel.js contains the mongoose schema:
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 contains the routes :
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 contains the getDrawings function:
//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 which correctly displays the image ( it is also used to add images to database, but that is not my current problem ) :
<!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>
the react page correctly displays the name of the image and remaining page but doesn't display the image and gives the error mentioned above, whereas imagesPage.ejs correctly displays everything. Please help me out.
Thank you :)
CodePudding user response:
When passing in variables in the following assignment:
let image = `data:{image.img.contentType};base64,$(data.img.data.toString('base64'))`;
You have to use ${ }
instead of $( )
let image = `data:${image.img.contentType};base64,${data.img.data.toString('base64')}`;
Assuming image.img.contentType
is also a variable in that scope
CodePudding user response:
so, as the server is sending a JSON image, you need to convert JSON to Buffer with Int8Array
then that needs to be converted to Blob, and then create a URL object:
try it:
let name = data.name;
const blob = new Blob([Int8Array.from(data.img.data)], {type: data.img.contentType });
let image = window.URL.createObjectURL(blob);