Spring boot, thymeleaf, не отображаются изображения на странице. 404

Фотографии иногда отображаются, но не сразу, если кучу раз по обновлять и время пройдет (и по очереди). Либо вообще не отображается ничего и вылетает GET http://localhost:8080/localStorage/videos/d7dd93c9-fbeb-4595-9af9-269bb80ba83e_photo_2024-06-16_20-15-42.jpg

404 (Not Found)

на каждое изображение при обновлении страницы.

По указанному пути изображение сохраняется сразу. Не понимаю, в чем дело. Может в кеше каком-то, хотя я кеш не использую на проекте нигде. Может в th:style что-то с кодировкой, например. Помогите пожалуйста.

        <div class="video-card-img" th:style="'background-image: url('+ ${currentVideo.getImage()} +');'" >
<form method="post" enctype="multipart/form-data"  sec:authorize="hasRole('ROLE_ADMIN')" th:action="@{/videos}" th:object="${Video}" class="video-form-container" id="video-form-container">
    <img src="/image/videos/krest.png" id="cross" class="cross">
    <div class="video-form-title">Добавление видео</div>
    <div class="video-form-name-container">
        <div class="video-form-name">Название</div>
        <input type="text" th:field="*{title}" required>
    </div>
    <div class="video-form-add-container">
        <div class="video-form-add-title">Добавьте видео</div>
        <input type="file" accept="video/mp4" th:field="*{video}" required>
    </div>
    <div class="video-form-add-container">
        <div class="video-form-add-title">Добавьте обложку</div>
        <input type="file" th:field="*{image}" accept=".jpg,.jpeg,.png" required>
    </div>
    <div class="form-videos-button-container"  id="form-videos-button-container" onclick="createVideo()">
        <img src="/image/videos/buttonPlus.png" class="form-add-button-img">
        <div class="form-videos-button-title">Добавить</div>
    </div>
    <input type="hidden" th:name="${_csrf.getParameterName()}" th:value="${_csrf.token}">
</form>
@GetMapping
    public String showVideos(Model model){
        model.addAttribute("Video", new VideoDto<MultipartFile>());
        model.addAttribute("videos", videoService.getVideos().stream().map(video->(
                factory.entityToDto(video))).collect(Collectors.toList()));

        boolean hasAddError = model.containsAttribute("addVideoErrorMessage");
        boolean hasDeleteError = model.containsAttribute("deleteVideoError");

        if(hasAddError){
            model.addAttribute("addVideoErrorMessage", model.getAttribute("addVideoErrorMessage"));
        }

        if(hasDeleteError){
            model.addAttribute("deleteVideoError", model.getAttribute("deleteVideoError"));
        }

        return "videos/videos";
    }

    @PostMapping
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    public String addVideoForm(@ModelAttribute("Video") @Valid VideoDto<MultipartFile> videoDto,
                                   BindingResult bindingResult,
                                   RedirectAttributes redirectAttributes) throws IOException {

        if(bindingResult.hasErrors()){
            redirectAttributes.addFlashAttribute("addVideoErrorMessage",
                    bindingResult.getAllErrors().get(0).getDefaultMessage());
        } else{
            videoService.addVideo(factory.dtoToEntity(videoDto));
        }

        return "redirect:/videos";
    }

@Service
@RequiredArgsConstructor
public class StorageService {
    public String saveMultipartFile(MultipartFile file, String saveToChapter) {
        try {
            String fileName = UUID.randomUUID().toString() + "_" + file.getOriginalFilename();
            Path destination = Paths.get("C:", "Users", "4amer", "Desktop", "1BIGPROJECT", "kultura",
                    "src", "main", "resources", "static", "localStorage",
                    saveToChapter, fileName);
            byte[] fileData = file.getBytes();
            Files.write(destination, fileData);
            return "/localStorage/" + saveToChapter + "/" + fileName;
        } catch (IOException e) {
            throw new ErrorCreatingVideoException("Не удалось сохранить файл");
        } catch (MaxUploadSizeExceededException exception){
            throw new ErrorCreatingVideoException("Слишком большой формат файла " + file.getOriginalFilename());
        }
    }
}
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {

    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{
        http.csrf(csrf ->
                csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()));

        http.formLogin(form ->
                        form.loginPage("/login")
                                .loginProcessingUrl("/perform-login-security")
                                .failureHandler(new CustomAuthenticationFailureHandler())
                                .defaultSuccessUrl("/", true)
                                .permitAll());


        http.authorizeHttpRequests(auth ->
                auth.requestMatchers(HttpMethod.GET, "*/admin/**").hasAuthority("ADMIN")//???????
                        .requestMatchers(HttpMethod.POST, "*/admin/**").hasAuthority("ADMIN")//???????
                        .anyRequest().permitAll());


        return http.build();
    }


}

Ответы (1 шт):

Автор решения: user616024

Дело действительно оказалось в кеше, решил проблему следующим образом:

@Configuration
public class WebConfig implements WebMvcConfigurer {
   

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/localStorage/**")
                .addResourceLocations("file:C:/Users/4amer/Desktop/1BIGPROJECT/kultura/src/main/resources/static/localStorage/")
                .setCachePeriod(0);
    }



}
→ Ссылка