Issue
I have the problem that my thymeleaf block don`t show image and shortcut icon on html page
I tried it with file path:
<img class="logo" th:src="@{src/main/resources/static/logo.png}" alt="Logo">
and also tried it with rest api:
<img class="logo" th:src="@{/api/v1/logo}" alt="Logo">
there is controller:
@RestController
@RequestMapping("/api/v1/logo")
public class LogoController {
@GetMapping(produces = MediaType.IMAGE_JPEG_VALUE)
public Resource getLogo() throws IOException {
return new ByteArrayResource(Files.toByteArray(new File("src/main/resources/static/logo.png")));
}
}
And I always get alt instead of image...
Solution
Problem 1: Reading the file correctly
If you're using the default configuration, then anything you put into src/main/resources
is copied to the classpath. Because of that, you should nowhere in your code refer to src/main/resources
, but to the classpath itself.
If you run locally, it might still work, but as soon as you run your JAR file somewhere else, it will break entirely.
So ideally, you should rewrite your controller as:
// Get location from classpath
URI location = getClass().getClassLoader().getResource("static/logo.png").toURI();
// Get file
Path file = Paths.get(location);
// Read bytes
return new ByteArrayResource(Files.readAllBytes(file));
Since retrieving a resource from a file is a common task, you don't really have to read the bytes though.
In stead of using ByteArrayResource
you can use FileSystemResource
:
// Get location from classpath
URI location = getClass().getClassLoader().getResource("static/logo.png").toURI();
// Get file
Path file = Paths.get(location);
return new FileSystemResource(file);
You can even make this shorter, because retrieving a resource from the classpath is so common that there is a ClasspathResource
class:
return new ClassPathResource("static/logo.png");
And that's not everything, it happens commonly that you need to serve web resources from the classpath, so in Spring Boot, everything that is in the classpath:static/
folder or classpath:public/
folder is already served on the web. So normally, your image is already available at http://localhost:8080/logo.png
without the need for your controller method.
So normally you can remove that controller method entirely.
Problem 2: Referring to the file correctly
This brings us to the second problem. Currently, you're referring to your image either with @{/api/v1/logo}
or @{src/main/resources/static/logo.png}
.
Thymeleaf interpretes @{path/to/file}
as a context-relative URL, so the only thing it does is prepend the context path if you have any and expects the file to be available at http://localhost:[serverport]/[contextpath]/path/to/file
.
But as we've established before, your image should be available at http://localhost:8080/logo.png
, and thus, you should use @{/logo.png}
:
<img class="logo" th:src="@{/logo.png}" alt="Logo">
If this doesn't work, then:
- You may have misconfigured your build tool to not include
src/main/resources
on the classpath. - You may have configured Spring Boot to not automatically serve whatever is inside of
classpath:static/
orclasspath:public/
.
Answered By - Dimitri Mestdagh
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.