Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

Dificuldade ao apresentar uma imagem estática na página HTML usando spring

Pessoal, não sei se estou fazendo algo errado mas simplesmente não consigo apresentar uma imagem .jpg na minha view. Tudo funciona perfeitamente bem na aplicação. Os controllers, intercepts, etc, tudo está ok, inclusive, imagens da web são renderizadas sem complicações. Os conteúdos estáticos é que parecem não funcionar... O curso não menciona esse problema e na internet a maior parte dos posts se referem a versões antigas do spring.

Criei o projeto pelo spring initializr, sendo que a estrutura de pastas criada automaticamente é a seguinte:

1.Projeto 1.1.src/main/java 1.1.1."<classes do projeto, model e controlles>" 1.2.src/main/resources 1.2.1.static 1.2.1.1.images 1.2.1.1.1teste.png 1.2.2templates 1.2.2.1.home.html

Dentro da home eu tento acessar o arquivo teste.png, porém sem sucesso... Segue abaixo as minhas tentativas: a) Já testei colocar a pasta images dentro da pasta templates, sem sucesso. b) Já testei colocar o teste.jpg diretamente na pasta template, sem sucesso. c) Já testei colocar o teste.jpg diretamente na pasta static, sem sucesso. d) Já testei os mais variados caminhos de src para a tag img (com e sem th do thymeleaf), todos sem sucesso, conforme abaixo: "img th:src="@{/resources/images/teste.png}" " "img src="/resources/images/teste.png" " "img src="resources/images/teste.png" " "img th:src="@{/resources/static/images/teste.png}" /" "img src="resources/static/images/teste.png" " "img th:src="@{/static/images/teste.png}" " "img src="/static/images/teste.png" " "img th:src="@{/templates/images/teste.png}" " "img src="/templates/images/teste.png" " "<img th:src="@{/images/teste.png}" " "img src="/images/teste.png"" "img th:src="@{/teste.png}" " "img src="teste.png" "

Ao carregar a página, percebi que o console do browser retorna um erro 404, pois tenta fazer um GET no endereço passado na imagem (exemplo de uma tentativa: http://localhost:8082/resources/images/teste.png 404)

Alguém tem ideia de como resolver isso no spring??

2 respostas

Apenas complementando... Pra resolver o problema eu tenho duas saídas:

1) Salvo as imagens dos usuários em um repositório da web... na hora de salvar eu gravo o caminho no meu banco e depois, ao ser requisitado, apresento na view;

2) Capturo o caminho relativo do projeto dentro da controller e gravo o nome do arquivo que o usuário escolheu no banco. O exemplo dessa alternativa está aqui embaixo, porém eu tenho consciência que essa não é a melhor saída porque qualquer alteração no diretório onde a aplicação está hospedada exige uma alteração no código. Eu imagino que o Srping tenha uma forma de pegar o caminho da pasta /static ou /template... só não sei como :(

A classe no controller fica assim:

//urlImagem é o nome passado pela view para chamar o método
@GetMapping("/images/{urlImagemLocal}")
    @ResponseBody
    public byte[] carregaImagensDinamicas(@PathVariable("urlImagemLocal") String nomeImagem) {

    File imagemArquivo = new File("./src/main/resources/templates/images/" + nomeImagem);

        try {
            return Files.readAllBytes(imagemArquivo.toPath());
        } catch (IOException e) {
            return null;
        }

    }
solução!

Voltando aqui porque pode ser útil para outras pessoas...

O meu problema era: Não conseguia utilizar arquivos estáticos (javascripts, css ou imagens) na view.

1- Eu percebi que o spring estava forçando a aplicação a chamar a requisição via controller. Sendo claro... ao usar, por exemplo, uma tag html <img src:"caminho_local.jpg"> o navegador mostrava erro no console, dizendo: GET http://localhost:8080/caminho_local.jpg 404. Ou seja, ele tentava encontrar um controller que respondia a essa requisição, ao invés de procurar na estrutura interna da pasta resources.

2- Como eu havia feito muitas alterações no projeto, resolvi criar um outro projeto "do zero", para ver se o spring realmente tratava nativamente as requisições estáticas daquela forma.

3- Ao criar um projeto, apenas inclui uma imagem na pasta resources/static e .... BINGO!!! A imagem apareceu! Não precisei fazer qualquer configuração para isso funcionar. É uma coisa realmente simples!

4- Voltei para o meu projeto e olhei as minhas classes de configurações (aquelas que tem a anotação @Configuration) para ter uma ideia sobre esse comportamento inesperado da aplicação.

5- Lembrei que eu havia criado um funcionalidade para guardar logs no banco por meio de Interceptor. Percebi que esse problema era relativamente comum entre os desenvolvedores, pois muitos fóruns tratavam a problemática. Porém a maior parte tratava de versões antigas do spring ou repetia configurações que eu já havia tentado sem sucesso.

6- Resolvi ler a documentação do Spring (essa ação foi ótima, porque acabei muitas coisas interessantes sobre o framework)! Como tinha um palpite que o problema estava sendo causado pela utilização do Interceptor, acabei encontrando a solução (https://docs.spring.io/spring-framework/docs/5.0.0.RELEASE/spring-framework-reference/web.html#mvc-config-static-resources)

7- O instrutor de spring do curso da Alura indicava a criação da classe WebConfig, estendendo uma classe chamada WebMvcConfigurationSupport cuja finalidade era adicionar o serviço de Interceptação. Ok isso funcionou corretamente, porém, por algum motivo, o método chamado addResourceHandlers, que serve para mapear as requisições, não funciona corretamente nesta classe.

8- Com apoio da documentação eu substitui a classe WebMvcConfigurationSupport pela interface WebMvcConfigurer e configurei o mapeamento das requisições que eram necessárias para o meu projeto e tudo passou a funcionar perfeitamente! Tanto WebMvcConfigurationSupport quanto a WebMvcConfigurer possuem métodos que adicionam Interceptors e Mapeamento de requisições. Segue abaixo como ficou a classe para o meu caso:

@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/resources/**")
                    .addResourceLocations("/public", "classpath:/static/")
                    .setCachePeriod(31556926);
    }

}