- 이번 시간에는 사용자가 자신의 프로필 사진을 변경할 수 있도록 하는 기능을 구현해보겠습니다.
📝 View
- 우선 자신의 프로필 사진만 변경할 수 있도록 제한하기 위해 View 페이지를 아래와 같이 구현하였습니다.
<c:choose>
<c:when test="${dto.user.id eq principal.user.id}">
<div class="profile-img-wrap story-border" onclick="popup('.modal-image')">
<form id="userProfileImageForm">
<input type="file" name="profileImageFile" style="display: none;" id="userProfileImageInput" />
</form>
<img class="profile-image" src="/upload/${dto.user.profile_image_url}" onerror="this.src='/images/person.jpeg'" id="userProfileImage" />
</div>
</c:when>
<c:otherwise>
<div class="profile-img-wrap story-border">
<img class="profile-image" src="/upload/${dto.user.profile_image_url}" onerror="this.src='/images/person.jpeg'" id="userProfileImage" />
</div>
</c:otherwise>
</c:choose>
- 즉, 자신의 프로필 페이지가 아니라면 아래와 같은 사진 업로드 모달이 보이지 않게 될 것입니다.
📝 Javascript
- 이후 ajax 통신을 통해 이미지를 서버에 저장하기 위해
js
파일에 아래와 같은 함수를 구현해주었습니다.
// (4) 유저 프로파일 사진 변경 (완)
function profileImageUpload(principalId) {
$("#userProfileImageInput").click();
$("#userProfileImageInput").on("change", (e) => {
let f = e.target.files[0];
if (!f.type.match("image.*")) {
alert("이미지를 등록해야 합니다.");
return;
}
// FormData 객체를 이용하면 form 태그의 필드와 그 값을 나타내는 일련의 key/value 쌍을 담을 수 있음
let userProfileImageForm = $("#userProfileImageForm")[0];
let formData = new FormData(userProfileImageForm);
// 서버에 이미지 전송하기
$.ajax({
type: "PUT",
url: `/api/user/${principalId}/profileImageUrl`,
data: formData,
contentType: false, // x-www-form-urlencoded로 파싱되는 것을 방지
processData: false, // contentType을 false로 설정할 경우 QueryString이 자동 설정되는 것을 방지
enctype: "multipart/form-data",
dataType: "json"
}).done(resp => {
// 사진 전송 성공시 이미지 변경
let reader = new FileReader();
reader.onload = (e) => {
$("#userProfileImage").attr("src", e.target.result);
}
reader.readAsDataURL(f); // 이 코드 실행시 reader.onload 실행됨.
}).fail(error => {
console.log(error);
});
});
}
📝 Controller
- 다음으로 컨트롤러에 해당 url을 요청받는 함수를 아래와 같이 구현하였습니다.
package com.cos.photogram.web.api;
...
@RequiredArgsConstructor
@RestController
public class UserApiController {
private final UserService userService;
...
@PutMapping("/api/user/{principalId}/profileImageUrl")
public ResponseEntity<?> profileImageUpdate(@PathVariable Long principalId, MultipartFile profileImageFile, @AuthenticationPrincipal PrincipalDetails principalDetails) {
User userEntity = userService.profileImageUpdate(principalId, profileImageFile);
principalDetails.setUser(userEntity);
return new ResponseEntity<>(new CMRespDto<>(1, "프로필 사진 변경 성공", null), HttpStatus.OK);
}
}
- 프로필 사진을 변경하면 세션 값을 실시간으로 바꿔주기 위해
@AuthenticationPrincipal
어노테이션을 추가로 사용하였습니다.
📝 Service
- 컨트롤러에서 호출한
profileImageUpdate()
함수는 아래와 같이 구현되어있습니다.
package com.cos.photogram.service;
...
@RequiredArgsConstructor
@Service
public class UserService {
private final UserRepository userRepository;
...
@Value("${file.path}")
private String uploadFolder;
...
@Transactional
public User profileImageUpdate(Long principalId, MultipartFile profileImageFile) {
UUID uuid = UUID.randomUUID();
String imageFileName = uuid + "_" + profileImageFile.getOriginalFilename();
Path imageFilePath = Paths.get(uploadFolder + imageFileName);
try {
Files.write(imageFilePath, profileImageFile.getBytes());
} catch(Exception e) {
e.printStackTrace();
}
User userEntity = userRepository.findById(principalId).orElseThrow(() -> {
return new CustomApiException("찾을 수 없는 사용자입니다.");
});
userEntity.setProfile_image_url(imageFileName);
return userEntity;
}
}
- 이전에
ImageService
에 구현해놓았던 코드의 일부분을 가져와 수정하였으며 더티 체킹을 통해 이미지 경로를 설정하고 있습니다.
📝 Result
- 이후 결과를 확인해보면 프로필 이미지가 알맞게 업로드되어 변경되는 것을 확인할 수 있으며, 현재 접속중인 사용자가 아닌 다른 사용자의 프로필 이미지를 클릭할 경우 프로필 이미지를 변경할 수 없도록 모달조차 나타나지 않는 것을 확인할 수 있습니다.
'🚗 Backend Toy Project > Photogram' 카테고리의 다른 글
[Photogram] 유효성 검사 자동화 - AOP 처리 (0) | 2022.07.18 |
---|---|
[Photogram] 댓글 구현 (0) | 2022.07.17 |
[Photogram] 인기 페이지 구현 (2) | 2022.07.16 |
[Photogram] 좋아요 구현하기 (0) | 2022.07.15 |
[Photogram] 스토리 페이지 (0) | 2022.07.14 |