javaspringimagethymeleafrendering

cannot get uploaded image to render when calling it from a file path stored in a database


Below is what I see when I run my code.
enter image description here

Thymeleaf code I am using:

<div>
    <img th:scr="@{/uploads/${image}}" alt="Uploaded Image" width="200px" height="200px"/>
</div>

The directory path starts with the file of my complete Java project... GEM/uploads/(what's stored).

When I run my controller code and I print it, I have a list of String and it prints correctly how the file should be.

@GetMapping("/images")
public String viewUserImages(Model model, User user) {
    user = userService.getCurrentUser();
    if (user != null) {
        List<ImageMetaData> img = imageService.getImagesByUser(user);
        List<String> images = ImageMetaData.filePathStartFromDate(img);
        for (String i : images) {
            System.out.println(i);
        }
        model.addAttribute("images", images); // Add images to the template
    } else {
        model.addAttribute("error", "You need to be logged in to view images.");
    }
    return "imageGallery";
}

my console prints... (which is stored by date and a random generated file name)

2025/02/23/e2ac3061-e334-4dec-9a08-4298475edc08.jpg

2025/02/23/e533359f-e8f1-46a7-90d2-c921299d10dc.jpg

These images are being stored correctly because I can see them in the folders. I tired to update permissions on my mac, but not exactly sure if I did it correctly. Can anyone experienced please help me figure out why my photos aren't displaying?


Solution

  • Thanks to ChatGPT! It helped but I just summarise our discussion:

    1. th:scr -> th:src
    2. Path variables in URLs are supposed to be defined using next syntax:
    <div>
        <img th:scr="@{/uploads/{image}(image=${image})}" alt="Uploaded Image" width="200px" height="200px"/>
    </div>
    
    1. By default files should be under src/main/resources/static
    /GEM
    │── /src
    │    ├── /main
    │    │   ├── /java/...
    │    │   ├── /resources
    │    │   │   ├── /static
    │    │   │   │   ├── /uploads
    │    │   │   │   │   ├── /2025
    │    │   │   │   │   │   ├── /02
    │    │   │   │   │   │   │   ├── /23
    │    │   │   │   │   │   │   │   ├── e2ac3061-e334-4dec-9a08-4298475edc08.jpg
    │    │   │   │   │   │   │   │   ├── e533359f-e8f1-46a7-90d2-c921299d10dc.jpg
    │    │   │   ├── /templates
    │    │   │   │   ├── imageGallery.html
    │    │   ├── /application.properties
    │── /target
    │── pom.xml
    
    

    Simple example:

    If you have image GEM/src/main/resources/static/image1.jpg then you can access it from Thymeleaf like that:

    <img th:scr="@{image1.jpg)}"
    

    If you have image GEM/src/main/resources/static/nestedFolder/image2.jpg then next way works:

    <img th:scr="@{nestedFolder/image2.jpg)}"
    

    BUT if you want to have images under project root, something like that:

    /GEM
    │── /uploads
    │    ├── /2025
    │    │   ├── /02
    │    │   │   ├── /23
    │    │   │   │   ├── e2ac3061-e334-4dec-9a08-4298475edc08.jpg
    │    │   │   │   ├── e533359f-e8f1-46a7-90d2-c921299d10dc.jpg
    │── /src
    │    ├── /main
    │    │   ├── /java/...
    │    │   ├── /resources
    │    │   │   ├── /templates
    │    │   │   │   ├── imageGallery.html
    │    │   ├── /application.properties
    │── /target
    │── pom.xml
    

    then you should tell it Spring explicitly:

    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            String uploadDir = Paths.get("uploads").toUri().toString();
            registry.addResourceHandler("/uploads/**").addResourceLocations(uploadDir);
        }
    }
    

    which means:

    "If a browser requests http://localhost/uploads/**, look for this file in the uploads/ folder in the project root (because by default Spring looks for this file in src/main/resources/static/)"