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);
}
}