Search code examples
htmlimageherokuthymeleaf

HTML for serving Images through Spring Boot from Database


I store avatar images in PGSQL in Heroku and I used to serve through API REST GET controller, everything fine. I'm now trying to serve through API REST URL at server domain, via thymeleaf, so I prepared an MVC for that. Everything is working, except that I can't use the server URL to embed into HTML tag in my frontend application, it shows a missing link, which I don't understand, because if I open the link itself in the browser it works well and shows the image.

What I'm trying to do is something similar to the google avatar HTML, I copied that google HTML simple code and served as it, in the google HTML works, but not with mine...

Google example: https://lh3.googleusercontent.com/a-/AOh14GgQ4X0_nQVH0NszR1-YGu90CIk40XSWT97uqW_V=s96-c

My output: https://chefscript.herokuapp.com/avatar?emailHash=7ad248c8b830100b95ae8fe57d6f07324b8d5c69872dcf4a5d280a993b8ab676

So, both works well, but I can only use the google one in my HTML IMG SRC at the frontend, my output shows a borken link. :(

My HTML Tempalte:

<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <title th:text="${title}"></title>
    <meta name="viewport" content="width=device-width, minimum-scale=0.1">
  </head>
  <body style="margin: 0px; background: #0e0e0e;">
    <img style="-webkit-user-select: none;margin: auto;" th:if="${avatarData != null}" th:src="'data:image/jpeg;base64,' + ${avatarData}">
    <img style="-webkit-user-select: none;margin: auto;" th:if="${avatarData == null}" th:src="@{${avatarURL}}">
  </body>
</html>

And my controller code:

@GetMapping("/avatar")
public String getAvatar(@RequestParam(name="emailHash", required=false, defaultValue="") String hashEmail, Model model) {

    User user = userRepository.findByHashEmail(hashEmail).orElseThrow(() -> new ResourceNotFoundException());
    byte[] image = userService.getImageBlobByEmailHash(hashEmail, true, false);
    model.addAttribute("title", "AVT-" + hashEmail);

    if ( image != null ) {
      model.addAttribute("avatarData", Base64.getEncoder().withoutPadding().encodeToString(image));
    } else { 
      if ( user.getAvatar() != "" && user.getAvatar() != null ) {
        model.addAttribute("avatarData", null);
        model.addAttribute("avatarURL", user.getAvatar());
      } else {
        model.addAttribute("avatarURL", "/img/avatar-128.png");
      }
    }
    return "avatar";
}

Finally my frontend, where the broken link shows:

<a href (click)="false" [routerLink]="'/social/user/'+user.hashEmail">
    <img class="s-ava-alone-img" width="150" height="150" [src]="'https://chefscript.herokuapp.com/avatar?emailHash='+user.hashEmail">
</a>

Solution

  • Find it. Issue with headers and response type. I wanted to use avatar images trhough HTML/TEXT to later one use in the IMG SRC at the Frontend. Bad strategy. I saw in the google one that the Content-Type header is set to image/jpeg and the Content-Disposition header is set to inline. This way it can be used later on.