diff --git a/src/main/java/org/khtml/hexagonal/domain/building/BlobManager.java b/src/main/java/org/khtml/hexagonal/domain/building/BlobManager.java index 652f99f..b33ff91 100644 --- a/src/main/java/org/khtml/hexagonal/domain/building/BlobManager.java +++ b/src/main/java/org/khtml/hexagonal/domain/building/BlobManager.java @@ -8,6 +8,7 @@ import org.springframework.stereotype.Component; import java.io.InputStream; +import java.util.UUID; @Component public class BlobManager { @@ -19,9 +20,10 @@ public class BlobManager { private String accountKey; public String storeFile(String filename, InputStream content, long length) { - BlobClient client = containerClient().getBlobClient(filename.trim()); + String filenameUUID = generateUniqueFilename(filename); + BlobClient client = containerClient().getBlobClient(filenameUUID); client.upload(content, length); - return "File uploaded with success!"; + return client.getBlobUrl(); } private BlobContainerClient containerClient() { @@ -34,4 +36,20 @@ private BlobContainerClient containerClient() { return blobServiceClient.getBlobContainerClient("images"); } + private String generateUniqueFilename(String originalFilename) { + String extension = ""; + int dotIndex = originalFilename.lastIndexOf('.'); + + // 파일 확장자 추출 + if (dotIndex > 0) { + extension = originalFilename.substring(dotIndex); + originalFilename = originalFilename.substring(0, dotIndex); + } + + // UUID 기반의 고유한 ID 생성 (8자리로 줄이기) + String uniqueID = UUID.randomUUID().toString().substring(0, 8); + + // 원래 파일 이름에 고유 ID 추가 + return originalFilename + "_" + uniqueID + extension; + } } diff --git a/src/main/java/org/khtml/hexagonal/domain/building/Building.java b/src/main/java/org/khtml/hexagonal/domain/building/Building.java index c7f3c71..67f99a9 100644 --- a/src/main/java/org/khtml/hexagonal/domain/building/Building.java +++ b/src/main/java/org/khtml/hexagonal/domain/building/Building.java @@ -108,5 +108,9 @@ public class Building { @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; - + + public void updateUser(User user) { + this.user = user; + } + } diff --git a/src/main/java/org/khtml/hexagonal/domain/building/BuildingController.java b/src/main/java/org/khtml/hexagonal/domain/building/BuildingController.java index bdcdc36..5c81de3 100644 --- a/src/main/java/org/khtml/hexagonal/domain/building/BuildingController.java +++ b/src/main/java/org/khtml/hexagonal/domain/building/BuildingController.java @@ -29,10 +29,11 @@ public ApiResponse getBuildingDetail( @PostMapping("/{building-id}/register") public ApiResponse registerBuilding( @RequestHeader("Authorization") String token, - @RequestParam("images") List multipartFiles + @RequestParam("images") List multipartFiles, + @PathVariable(name = "building-id") String buildingId ) throws IOException { User requestUser = jwtValidator.getUserFromToken(token); - buildingService.registerBuilding(requestUser, multipartFiles); + buildingService.registerBuilding(buildingId, requestUser, multipartFiles); return ApiResponse.success(); } diff --git a/src/main/java/org/khtml/hexagonal/domain/building/BuildingImage.java b/src/main/java/org/khtml/hexagonal/domain/building/BuildingImage.java index 2b5a085..dffab5b 100644 --- a/src/main/java/org/khtml/hexagonal/domain/building/BuildingImage.java +++ b/src/main/java/org/khtml/hexagonal/domain/building/BuildingImage.java @@ -3,6 +3,7 @@ import jakarta.persistence.*; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import org.khtml.hexagonal.domain.common.BaseEntity; @@ -21,4 +22,10 @@ public class BuildingImage extends BaseEntity { @JoinColumn(name = "image_id") private Image image; + @Builder + public BuildingImage(Building building, Image image) { + this.building = building; + this.image = image; + } + } diff --git a/src/main/java/org/khtml/hexagonal/domain/building/BuildingImageRepository.java b/src/main/java/org/khtml/hexagonal/domain/building/BuildingImageRepository.java new file mode 100644 index 0000000..26afcee --- /dev/null +++ b/src/main/java/org/khtml/hexagonal/domain/building/BuildingImageRepository.java @@ -0,0 +1,6 @@ +package org.khtml.hexagonal.domain.building; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface BuildingImageRepository extends JpaRepository { +} diff --git a/src/main/java/org/khtml/hexagonal/domain/building/Image.java b/src/main/java/org/khtml/hexagonal/domain/building/Image.java index 9b314ce..80209c0 100644 --- a/src/main/java/org/khtml/hexagonal/domain/building/Image.java +++ b/src/main/java/org/khtml/hexagonal/domain/building/Image.java @@ -2,6 +2,7 @@ import jakarta.persistence.*; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import org.khtml.hexagonal.domain.common.BaseEntity; @@ -19,4 +20,10 @@ public class Image extends BaseEntity { @JoinColumn(name = "user_id") private User user; + @Builder + public Image(String url, User user) { + this.url = url; + this.user = user; + } + } diff --git a/src/main/java/org/khtml/hexagonal/domain/building/ImageRepository.java b/src/main/java/org/khtml/hexagonal/domain/building/ImageRepository.java new file mode 100644 index 0000000..437efa3 --- /dev/null +++ b/src/main/java/org/khtml/hexagonal/domain/building/ImageRepository.java @@ -0,0 +1,6 @@ +package org.khtml.hexagonal.domain.building; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ImageRepository extends JpaRepository { +} diff --git a/src/main/java/org/khtml/hexagonal/domain/building/application/BuildingService.java b/src/main/java/org/khtml/hexagonal/domain/building/application/BuildingService.java index a251c6f..5f6df5a 100644 --- a/src/main/java/org/khtml/hexagonal/domain/building/application/BuildingService.java +++ b/src/main/java/org/khtml/hexagonal/domain/building/application/BuildingService.java @@ -2,24 +2,30 @@ import lombok.RequiredArgsConstructor; import org.khtml.hexagonal.domain.ai.dto.BuildingUpdate; -import org.khtml.hexagonal.domain.building.BlobManager; -import org.khtml.hexagonal.domain.building.Building; -import org.khtml.hexagonal.domain.building.BuildingDetailResponse; -import org.khtml.hexagonal.domain.building.BuildingRepository; +import org.khtml.hexagonal.domain.building.*; import org.khtml.hexagonal.domain.user.User; +import org.khtml.hexagonal.domain.user.UserRepository; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.util.List; +import java.util.Objects; @RequiredArgsConstructor +@Transactional(readOnly = true) @Service public class BuildingService { private final BuildingRepository buildingRepository; + private final BuildingImageRepository buildingImageRepository; + private final ImageRepository imageRepository; + private final UserRepository userRepository; private final BlobManager blobManager; + + @Transactional public Building createBuilding(Building building) { return buildingRepository.save(building); } @@ -33,6 +39,7 @@ public void deleteBuilding(Long id) { buildingRepository.deleteById(id); } + @Transactional public Building updateBuilding(String buildingId, BuildingUpdate buildingUpdate) { Building existingBuilding = getBuilding(buildingId); existingBuilding.setStructureReason(buildingUpdate.getStructureReason()); @@ -54,10 +61,30 @@ public Building updateBuilding(String buildingId, BuildingUpdate buildingUpdate) return buildingRepository.save(existingBuilding); } - public void registerBuilding(User requestUser, List multipartFiles) throws IOException { - MultipartFile file = multipartFiles.getFirst(); - String url = blobManager.storeFile(file.getOriginalFilename(), file.getInputStream(), file.getSize()); + @Transactional + public void registerBuilding(String buildingId, User requestUser, List multipartFiles) throws IOException { + for(MultipartFile file : multipartFiles) { + String url = blobManager.storeFile(file.getOriginalFilename(), file.getInputStream(), file.getSize()); + + User user = userRepository.findById(requestUser.getId()).orElseThrow(() -> new IllegalArgumentException("User not found")); + Building building = buildingRepository.findBuildingByGisBuildingId(buildingId) + .orElseThrow(() -> new IllegalArgumentException("Building not found")); + + building.updateUser(user); + + Image image = Image.builder() + .url(url) + .user(user) + .build(); + + BuildingImage buildingImage = BuildingImage.builder() + .building(building) + .image(image) + .build(); + imageRepository.save(image); + buildingImageRepository.save(buildingImage); + } } }