Merge pull request #16 from SlimusMinus/fix_images
added many images in post
This commit is contained in:
@@ -1,13 +1,16 @@
|
|||||||
package com.krylov.refound.controller;
|
package com.krylov.refound.controller;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.krylov.refound.dto.PostRequest;
|
import com.krylov.refound.dto.PostRequest;
|
||||||
import com.krylov.refound.dto.PostResponse;
|
import com.krylov.refound.dto.PostResponse;
|
||||||
import com.krylov.refound.dto.StatusUpdateRequest;
|
import com.krylov.refound.dto.StatusUpdateRequest;
|
||||||
import com.krylov.refound.enums.PostType;
|
import com.krylov.refound.enums.PostType;
|
||||||
import com.krylov.refound.service.PostService;
|
import com.krylov.refound.service.PostService;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
@@ -31,11 +34,13 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
public class PostController {
|
public class PostController {
|
||||||
|
|
||||||
private final PostService service;
|
private final PostService service;
|
||||||
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||||
public PostRequest create(@ModelAttribute PostRequest request, @RequestPart(value = "image", required = false) MultipartFile image) {
|
public PostRequest create(@ModelAttribute PostRequest request,
|
||||||
|
@RequestParam(value = "images", required = false) List<MultipartFile> images) {
|
||||||
log.info(request.toString());
|
log.info(request.toString());
|
||||||
return service.create(request, image);
|
return service.create(request, images);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
@@ -44,7 +49,7 @@ public class PostController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public List<PostResponse> getById(@PathVariable Long id) {
|
public List<PostResponse> getById(@PathVariable Long id) {
|
||||||
return service.getById(id);
|
return service.getById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,8 +64,8 @@ public class PostController {
|
|||||||
@RequestParam(required = false) String description,
|
@RequestParam(required = false) String description,
|
||||||
@RequestParam(required = false) String category,
|
@RequestParam(required = false) String category,
|
||||||
@RequestParam(required = false) String phone,
|
@RequestParam(required = false) String phone,
|
||||||
@RequestParam(value = "image", required = false) MultipartFile image
|
@RequestParam(value = "images", required = false) List<MultipartFile> images,
|
||||||
) {
|
@RequestParam(value = "existingImages", required = false) String existingImagesJson) {
|
||||||
PostRequest request = new PostRequest();
|
PostRequest request = new PostRequest();
|
||||||
request.setType(PostType.from(type));
|
request.setType(PostType.from(type));
|
||||||
request.setTitle(title);
|
request.setTitle(title);
|
||||||
@@ -70,8 +75,15 @@ public class PostController {
|
|||||||
request.setLatitude(latitude);
|
request.setLatitude(latitude);
|
||||||
request.setLongitude(longitude);
|
request.setLongitude(longitude);
|
||||||
request.setAddress(address);
|
request.setAddress(address);
|
||||||
|
List<String> existingUrls;
|
||||||
|
try {
|
||||||
|
existingUrls = existingImagesJson != null ? Arrays.asList(
|
||||||
|
objectMapper.readValue(existingImagesJson, String[].class)) : List.of();
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
return service.update(id, request, image);
|
return service.update(id, request, images, existingUrls);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
@@ -80,7 +92,8 @@ public class PostController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PatchMapping("/{id}/status")
|
@PatchMapping("/{id}/status")
|
||||||
public PostResponse updateStatus(@PathVariable Long id, @RequestBody StatusUpdateRequest request) {
|
public PostResponse updateStatus(@PathVariable Long id,
|
||||||
|
@RequestBody StatusUpdateRequest request) {
|
||||||
return service.updateStatus(id, request.getStatus());
|
return service.updateStatus(id, request.getStatus());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public class PostService {
|
|||||||
private final UserService userService;
|
private final UserService userService;
|
||||||
private final FavoriteRepository favoriteRepository;
|
private final FavoriteRepository favoriteRepository;
|
||||||
|
|
||||||
public PostRequest create(PostRequest request, MultipartFile image) {
|
public PostRequest create(PostRequest request, List<MultipartFile> images) {
|
||||||
|
|
||||||
Post post = mapper.toEntity(request);
|
Post post = mapper.toEntity(request);
|
||||||
post.setCreatedAt(LocalDateTime.now());
|
post.setCreatedAt(LocalDateTime.now());
|
||||||
@@ -52,21 +52,32 @@ public class PostService {
|
|||||||
post.setUser(userService.getCurrentUser()); // присваиваем текущего пользователя
|
post.setUser(userService.getCurrentUser()); // присваиваем текущего пользователя
|
||||||
repository.save(post); // сначала сохраняем post, чтобы получить id
|
repository.save(post); // сначала сохраняем post, чтобы получить id
|
||||||
|
|
||||||
if (image != null && !image.isEmpty()) {
|
if (images != null && !images.isEmpty()) {
|
||||||
String filename = UUID.randomUUID() + "_" + image.getOriginalFilename();
|
|
||||||
Path uploadDir = Paths.get("uploads");
|
Path uploadDir = Paths.get("uploads");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Files.createDirectories(uploadDir);
|
Files.createDirectories(uploadDir);
|
||||||
Files.copy(image.getInputStream(), uploadDir.resolve(filename));
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("Не удалось сохранить файл: " + filename, e);
|
throw new RuntimeException("Не удалось создать директорию загрузки", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
Image img = new Image();
|
for (MultipartFile image : images) {
|
||||||
img.setUrl("/uploads/" + filename);
|
if (image == null || image.isEmpty()) {
|
||||||
img.setPost(post);
|
continue;
|
||||||
imageRepository.save(img);
|
}
|
||||||
|
|
||||||
|
String filename = UUID.randomUUID() + "_" + image.getOriginalFilename();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Files.copy(image.getInputStream(), uploadDir.resolve(filename));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Не удалось сохранить файл: " + filename, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Image img = new Image();
|
||||||
|
img.setUrl("/uploads/" + filename);
|
||||||
|
img.setPost(post);
|
||||||
|
imageRepository.save(img);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
@@ -146,8 +157,7 @@ public class PostService {
|
|||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PostResponse update(Long id, PostRequest request, MultipartFile image) {
|
public PostResponse update(Long id, PostRequest request, List<MultipartFile> images, List<String> existingUrls) {
|
||||||
|
|
||||||
Post post = repository.findById(id)
|
Post post = repository.findById(id)
|
||||||
.orElseThrow(() -> new ApiException(
|
.orElseThrow(() -> new ApiException(
|
||||||
ErrorCode.NOT_FOUND,
|
ErrorCode.NOT_FOUND,
|
||||||
@@ -162,41 +172,59 @@ public class PostService {
|
|||||||
}
|
}
|
||||||
post.setPhone(request.getPhone());
|
post.setPhone(request.getPhone());
|
||||||
post.setType(request.getType());
|
post.setType(request.getType());
|
||||||
if (request.getLatitude() != null && request.getLongitude() != null){
|
|
||||||
|
if (request.getLatitude() != null && request.getLongitude() != null) {
|
||||||
post.setLatitude(request.getLatitude());
|
post.setLatitude(request.getLatitude());
|
||||||
post.setLongitude(request.getLongitude());
|
post.setLongitude(request.getLongitude());
|
||||||
String address = nominatimService.getAddress(request.getLatitude().toString(), request.getLongitude().toString());
|
String address = nominatimService.getAddress(
|
||||||
|
request.getLatitude().toString(), request.getLongitude().toString());
|
||||||
post.setCity(address);
|
post.setCity(address);
|
||||||
} else {
|
} else {
|
||||||
post.setCity(request.getAddress());
|
post.setCity(request.getAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image != null && !image.isEmpty()) {
|
List<String> keepUrls = existingUrls != null ? existingUrls : List.of();
|
||||||
// удаляем старые картинки с диска
|
|
||||||
post.getImages().forEach(img -> {
|
|
||||||
try {
|
|
||||||
Files.deleteIfExists(Paths.get("." + img.getUrl()));
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.warn("Не удалось удалить файл: {}", img.getUrl());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// очищаем список (orphanRemoval = true удалит из БД)
|
|
||||||
post.getImages().clear();
|
|
||||||
|
|
||||||
// сохраняем новую картинку
|
// удаляем те картинки, которых нет среди "оставленных" с фронта
|
||||||
String filename = UUID.randomUUID() + "_" + image.getOriginalFilename();
|
List<Image> toRemove = post.getImages().stream()
|
||||||
|
.filter(img -> !keepUrls.contains(img.getUrl()))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
toRemove.forEach(img -> {
|
||||||
|
try {
|
||||||
|
Files.deleteIfExists(Paths.get("." + img.getUrl()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.warn("Не удалось удалить файл: {}", img.getUrl());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
post.getImages().removeAll(toRemove); // orphanRemoval = true удалит из БД
|
||||||
|
|
||||||
|
// добавляем новые загруженные файлы
|
||||||
|
if (images != null && !images.isEmpty()) {
|
||||||
Path uploadDir = Paths.get("uploads");
|
Path uploadDir = Paths.get("uploads");
|
||||||
try {
|
try {
|
||||||
Files.createDirectories(uploadDir);
|
Files.createDirectories(uploadDir);
|
||||||
Files.copy(image.getInputStream(), uploadDir.resolve(filename));
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("Не удалось сохранить файл: " + filename, e);
|
throw new RuntimeException("Не удалось создать директорию загрузки", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
Image img = new Image();
|
for (MultipartFile image : images) {
|
||||||
img.setUrl("/uploads/" + filename);
|
if (image == null || image.isEmpty()) {
|
||||||
img.setPost(post);
|
continue;
|
||||||
post.getImages().add(img);
|
}
|
||||||
|
String filename = UUID.randomUUID() + "_" + image.getOriginalFilename();
|
||||||
|
try {
|
||||||
|
Files.copy(image.getInputStream(), uploadDir.resolve(filename));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Не удалось сохранить файл: " + filename, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Image img = new Image();
|
||||||
|
img.setUrl("/uploads/" + filename);
|
||||||
|
img.setPost(post);
|
||||||
|
post.getImages().add(img);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Post updated = repository.save(post);
|
Post updated = repository.save(post);
|
||||||
|
|||||||
Reference in New Issue
Block a user