diff --git a/.gitignore b/.gitignore index c2065bc..0350373 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ build/ !gradle/wrapper/gradle-wrapper.jar !**/src/main/**/build/ !**/src/test/**/build/ +uploads/ ### STS ### .apt_generated diff --git a/src/main/java/club/inq/team1/config/WebMvcConfig.java b/src/main/java/club/inq/team1/config/WebMvcConfig.java index 5532347..888727e 100644 --- a/src/main/java/club/inq/team1/config/WebMvcConfig.java +++ b/src/main/java/club/inq/team1/config/WebMvcConfig.java @@ -23,13 +23,14 @@ public void addCorsMappings(CorsRegistry registry) { .maxAge(3600); } - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("/images/**") // ToDo 상수 처리 필요 - .addResourceLocations("file:///C:/images/") // 배포 환경에선 수정 필요 -// .addResourceLocations("file:///home/user/images/") - .setCacheControl(CacheControl.maxAge(Duration.ofSeconds(3600))) - .resourceChain(true) - .addResolver(new PathResourceResolver()); - } + /** 없어도 될듯? */ +// @Override +// public void addResourceHandlers(ResourceHandlerRegistry registry) { +// registry.addResourceHandler("/images/**") // ToDo 상수 처리 필요 +// .addResourceLocations("file:///C:/images/") // 배포 환경에선 수정 필요 +//// .addResourceLocations("file:///home/user/images/") +// .setCacheControl(CacheControl.maxAge(Duration.ofSeconds(3600))) +// .resourceChain(true) +// .addResolver(new PathResourceResolver()); +// } } diff --git a/src/main/java/club/inq/team1/constant/ImagePath.java b/src/main/java/club/inq/team1/constant/ImagePath.java new file mode 100644 index 0000000..87a1d0a --- /dev/null +++ b/src/main/java/club/inq/team1/constant/ImagePath.java @@ -0,0 +1,19 @@ +package club.inq.team1.constant; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public enum ImagePath { + WINDOW("C:/images/"), + LINUX("home/user/images/"), + SAVE_PROFILE("profile/" + LocalDateTime.now().format(DateTimeFormatter.BASIC_ISO_DATE) + "/"); + private final String path; + + ImagePath(String path) { + this.path = path; + } + + public String getPath() { + return WINDOW.path + path; + } +} diff --git a/src/main/java/club/inq/team1/controller/LoginController.java b/src/main/java/club/inq/team1/controller/LoginController.java deleted file mode 100644 index e893852..0000000 --- a/src/main/java/club/inq/team1/controller/LoginController.java +++ /dev/null @@ -1,12 +0,0 @@ -package club.inq.team1.controller; - -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; - -@Controller -public class LoginController { - @GetMapping("/login") - public String loginP(){ - return "login.html"; - } -} diff --git a/src/main/java/club/inq/team1/controller/UserController.java b/src/main/java/club/inq/team1/controller/UserController.java index b685315..23c1feb 100644 --- a/src/main/java/club/inq/team1/controller/UserController.java +++ b/src/main/java/club/inq/team1/controller/UserController.java @@ -22,7 +22,9 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; @RestController @RequestMapping("/api/users") @@ -113,7 +115,7 @@ public ResponseEntity updateCurrentUserPassword(@RequestBody @Valid Update public ResponseEntity getUserProfile(@PathVariable("id") Long id){ User user = userService.getUserProfile(id); UserInfo userInfo = user.getUserInfo(); - + // todo 수정 필요 PublicUserProfileDTO publicUserProfileDTO = new PublicUserProfileDTO(); publicUserProfileDTO.setUserId(user.getUserId()); publicUserProfileDTO.setNickname(userInfo.getNickname()); @@ -122,4 +124,15 @@ public ResponseEntity getUserProfile(@PathVariable("id") L return ResponseEntity.status(200).body(publicUserProfileDTO); } + + @PostMapping(value = "/my/image", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}, produces = {MediaType.APPLICATION_JSON_VALUE}) + public ResponseEntity setProfileImage(@RequestPart("image")MultipartFile image) { + boolean b = userService.setUserProfileImage(image); + return ResponseEntity.status(200).body(Boolean.toString(b)); + } + + @GetMapping(value = "/{userId}/image", produces = {MediaType.IMAGE_JPEG_VALUE, MediaType.IMAGE_PNG_VALUE}) + public ResponseEntity getProfileImage(@PathVariable("userId") Long userId){ + return ResponseEntity.ok(userService.getUserProfileImage(userId)); + } } diff --git a/src/main/java/club/inq/team1/dto/projection/ProfileImageProjectionDTO.java b/src/main/java/club/inq/team1/dto/projection/ProfileImageProjectionDTO.java new file mode 100644 index 0000000..fa60965 --- /dev/null +++ b/src/main/java/club/inq/team1/dto/projection/ProfileImageProjectionDTO.java @@ -0,0 +1,5 @@ +package club.inq.team1.dto.projection; + +public interface ProfileImageProjectionDTO { + String getProfileImagePath(); +} diff --git a/src/main/java/club/inq/team1/entity/UserInfo.java b/src/main/java/club/inq/team1/entity/UserInfo.java index 7bc1846..b6dff7e 100644 --- a/src/main/java/club/inq/team1/entity/UserInfo.java +++ b/src/main/java/club/inq/team1/entity/UserInfo.java @@ -58,6 +58,9 @@ public class UserInfo { @Column(name = "birth") private Date birth; + @Column(name = "profile_image_path") + private String profileImagePath; + @Temporal(TemporalType.TIMESTAMP) @Column(name = "created_at") @CreatedDate diff --git a/src/main/java/club/inq/team1/repository/UserInfoRepository.java b/src/main/java/club/inq/team1/repository/UserInfoRepository.java index aabaf56..5a1c594 100644 --- a/src/main/java/club/inq/team1/repository/UserInfoRepository.java +++ b/src/main/java/club/inq/team1/repository/UserInfoRepository.java @@ -1,8 +1,12 @@ package club.inq.team1.repository; +import club.inq.team1.dto.projection.ProfileImageProjectionDTO; +import club.inq.team1.entity.User; import club.inq.team1.entity.UserInfo; +import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; public interface UserInfoRepository extends JpaRepository { boolean existsByNickname(String nickname); + Optional findProfileImagePathByUser(User user); } diff --git a/src/main/java/club/inq/team1/service/UserService.java b/src/main/java/club/inq/team1/service/UserService.java index 8652554..24228fe 100644 --- a/src/main/java/club/inq/team1/service/UserService.java +++ b/src/main/java/club/inq/team1/service/UserService.java @@ -5,6 +5,7 @@ import club.inq.team1.dto.request.UserJoinDTO; import club.inq.team1.entity.User; import java.util.Optional; +import org.springframework.web.multipart.MultipartFile; public interface UserService { User acceptUser(UserJoinDTO userJoinDTO); @@ -14,4 +15,6 @@ public interface UserService { User updatePrivateInfo(PutUserPrivateInfoDTO putUserPrivateInfoDTO); User updatePassword(UpdateUserPasswordDTO updateUserPasswordDTO); User getUserProfile(Long id); + boolean setUserProfileImage(MultipartFile multipartFile); + byte[] getUserProfileImage(Long userId); } diff --git a/src/main/java/club/inq/team1/service/impl/UserServiceImpl.java b/src/main/java/club/inq/team1/service/impl/UserServiceImpl.java index 52a9576..6469166 100644 --- a/src/main/java/club/inq/team1/service/impl/UserServiceImpl.java +++ b/src/main/java/club/inq/team1/service/impl/UserServiceImpl.java @@ -1,5 +1,7 @@ package club.inq.team1.service.impl; +import club.inq.team1.constant.ImagePath; +import club.inq.team1.dto.projection.ProfileImageProjectionDTO; import club.inq.team1.dto.request.PutUserPrivateInfoDTO; import club.inq.team1.dto.request.UpdateUserPasswordDTO; import club.inq.team1.dto.request.UserJoinDTO; @@ -9,12 +11,20 @@ import club.inq.team1.repository.UserRepository; import club.inq.team1.service.UserService; import jakarta.transaction.Transactional; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.Optional; +import java.util.UUID; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; @Log4j2 @Service @@ -101,4 +111,51 @@ public User updatePassword(UpdateUserPasswordDTO updateUserPasswordDTO) { public User getUserProfile(Long id) { return userRepository.findById(id).orElseThrow(); } + + @Override + @Transactional + public boolean setUserProfileImage(MultipartFile multipartFile) { + UserInfo userInfo = getCurrentLoginUser().orElseThrow().getUserInfo(); + + // 이전 이미지 제거 + String profileImagePath = userInfo.getProfileImagePath(); + if(profileImagePath != null) { + File prevProfileImage = Path.of(profileImagePath).toFile(); + if (prevProfileImage.exists()) { + prevProfileImage.delete(); + } + } + + // 프로필 이미지 저장 경로 C:/images/profile/yyyyMMdd/randomUUID+originalName.format + String profilePath = ImagePath.SAVE_PROFILE.getPath(); + + String imageFileStoredName = UUID.randomUUID() + multipartFile.getOriginalFilename(); + String filePath = profilePath + imageFileStoredName; + try { + File f = new File(filePath); + f.mkdirs(); + multipartFile.transferTo(f); + userInfo.setProfileImagePath(filePath); + userInfoRepository.save(userInfo); + } catch (IOException e) { + throw new RuntimeException(e); + } + + return true; + } + + @Override + public byte[] getUserProfileImage(Long userId){ + User user = userRepository.findById(userId).orElseThrow(); + ProfileImageProjectionDTO profileImageProjectionDTO = userInfoRepository.findProfileImagePathByUser(user) + .orElseThrow(); + + String profileImagePath = profileImageProjectionDTO.getProfileImagePath(); + + try { + return Files.readAllBytes(Path.of(profileImagePath)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } } diff --git a/src/main/resources/static/login.html b/src/main/resources/static/login.html deleted file mode 100644 index 1b08b92..0000000 --- a/src/main/resources/static/login.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - LOGIN - - -
- - - -
-
- -
- - \ No newline at end of file