I am working on a website where I am getting images from a database. The images are stored as “bytea” variables in a Postgres SQL database. As from all I’ve researched on stackoverflow and other sources, if the image is correctly encoded (i.e., byte64) and I specify the string as the image (i.e., ) source, it should load correctly.
My image text variable is confirmed to be a string variable, and it is of form “data:image/jpeg;base64,aVZCT1J3MEtHZ29BQUFBTlN…..”. I’m pasting my whole React component below. The variable I just mentioned is named “imgTest”, and after the data loads, I continue to only see “test image” instead of the photo.
import { useState, useEffect } from 'react'
import axios from 'axios'
function Projects() {
const [data, setData] = useState([]);
const [offset, setOffset] = useState(0);
const [loading, setLoading] = useState(false);
const [initialLoad, setInitialLoad] = useState(true);
const [projectData, setProjectData] = useState([]);
const [imgTest, setImgTest] = useState('')
useEffect(() => {
loadData(0, 10);
}, []);
const loadData = async(offset, limit) => {
setLoading(true);
try {
const response = await axios.get('http://localhost:3000/api/projects', { params: { offset, limit } });
const newData = Array.isArray(response.data) ? response.data.rows : [response.data.rows];
// Convert byte arrays to Base64 strings
const processedData = newData.map(item => {
const updatedItem = { ...item };
if (item.mainphoto && item.mainphoto.data) {
const base64Flag = 'data:image/jpeg;base64,';
const mainPhotoStr = arrayBufferToBase64(item.mainphoto.data);
updatedItem.mainphoto = base64Flag + mainPhotoStr;
}
if (item.auxphoto1 && item.auxphoto1.data) {
const base64Flag = 'data:image/jpeg;base64,';
const auxPhotoStr = arrayBufferToBase64(item.auxphoto1.data);
updatedItem.auxphoto1 = base64Flag + auxPhotoStr;
}
return updatedItem;
});
setData((prevData) => [...prevData, ...newData]);
setOffset(offset + limit);
} catch (error) {
console.log('Error fetching data:', error);
}
setLoading(false);
};
const arrayBufferToBase64 = (buffer) => {
let binary = '';
const bytes = new Uint8Array(buffer);
const len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
};
useEffect(() => {
if (data.length > 0 && data[0]) {
////////////////////
const base64Flag = 'data:image/jpeg;base64,';
const imageString = base64Flag + arrayBufferToBase64(data[0][0].auxphoto1['data']);
// console.log('image String',imageString);
setImgTest(imageString);
// console.log('image test',imgTest);
/////////////////////
const projectData = data.map((item, index) => (
<div className='project' key={index} >
{item[0].clientname}
{item[0].clienttag1}
{item[0].clienttag2}
{item[0].clienttag3}
{/* {item[0].mainphoto && <img src={item[0].mainphoto} alt="Project Main" />} */}
</div>
));
setProjectData(projectData);
}
}, [data]);
useEffect(() => {
console.log('imgTest', imgTest);
}, [imgTest]);
const handleScroll = () => {
if (window.innerHeight + document.documentElement.scrollTop === document.documentElement.offsetHeight) {
loadData(offset, initialLoad ? 10 : 50);
setInitialLoad(false);
}
};
useEffect(() => {
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, [offset]);
return (
<>
<div className="projects">
{/* Image below will not load. Only shows alt text */}
{data.length > 0 ? <img src={imgTest} alt="test image" /> : 'Not Yet'}
</div>
</>
);
}
export default Projects;
Any thoughts or direction would be appreciated!