Problem to display images in the browser in Nextjs that are not stored in /public folder?

79 Views Asked by At

I am working with Next.js as a full-stack framework, using API route handlers in the backend.

I have stored the images in a Post method in the /uploads directory using the fs.writeFile method, and then I stored only the path to the image. This works fine I can see the image, but when I try to call it in the browser, I can't. I have tried to use and but with no success; I only get 404, 400, and in the terminal console: [0] The requested resource isn't a valid image for /uploads/images/43820915700090.jpg received text/html; charset=utf-8.

If I store the images under the /public folder, it works, but I have heard that the public folder only compiles during the build process and only serves for static content like icons and static images.

I know that I can use services like Cloudinary (I have used before) or S3 to give me a public url and then use the image , but the client doesn't want that. What should I do?

1

There are 1 best solutions below

0
Mahmoud Timoumi On BEST ANSWER

I have found the solution:

Next.js only uses the images that are stored in the public folder. However, the problem is that this folder serves the static content, so in the build process, it will copy /public into /.next/public, and I can't serve dynamic images from there.

To display dynamic paths that are stored in the database, I have used the fs:node utility to read the image in a React component, and then called it in page.jsx as shown below:

import fs from 'fs';
import path from 'path';
    
const MyImageComponent = ({ imageName, alt, width, height }) => {
      let startTime = performance.now()
      const imagePath = path.join(process.cwd(),  imageName);
    
      try {
        const ext = path.extname(imagePath).slice(1);
        console.log(ext)
        const image = fs.readFileSync(imagePath, 'base64');
        const imageUrl = `data:image/${ext};base64,${image}`;
        let endTime = performance.now()
    
        console.log(`reading the image took ${endTime - startTime} milliseconds`) // to test the time takes to render the image ===> between 0.2xx milliseconds and 1,xx second.
        
        return <img src={imageUrl} alt={alt} width={width} height={height} />;
      } catch (error) {
        console.error('Error reading image file:', error);
        return null;
      }
    };

export default MyImageComponent;

and in page.jsx I called it :

export default function Home(){ 
  return (
    <MyImageComponent  imageName ="./app/images/21356888.png" />
  )
}