반응형

profile.html
- profile-img-wrap story-border 를 클릭했을때 popup 메소드가 호출되면서 modal-image 가 팝업된다.
- 이 modal-image의  '사진업로드'를 클릭하면 profileImageUpload() 함수가 호출된다.
- profileImageUpload 함수에 페이지 유저의 아이디와 로그인 유저 아이디를 전달한다. 

...
<div class="profile-left">
  <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="" th:src="*{profileImageUrl}"
         onerror="this.src='/images/person.jpeg'" id="userProfileImage" />
  </div>
</div>
...


<!--프로필사진 바꾸기 모달-->
<div class="modal-image" onclick="modalImage()">
  <div class="modal">
    <p>프로필 사진 바꾸기</p>
    <button onclick="profileImageUpload()" th:onclick="|profileImageUpload('${dto.user.id}','${#authentication.principal.user.id}')|">사진 업로드</button>
    <button onclick="closePopup('.modal-image')">취소</button>
  </div>
</div>

 

profile.js
- 페이지주인 아이디와 로그인 유저 아이드를 받는다.
- 페이지 유저 아이디랑 로그인 유저가 동일하다면 자동으로 userProfileImageInput 부분을 클릭시킨다.
1. 서버에 이미지 전송
- userProfileImageForm의 0번째 요소를 찾아서  profileImageForm변수에 넣어준다. 
- ajax로 이 데이터를 전송하려면 FormData로 감싸야 한다. 
   =>profileImageForm은 폼테그 그 자체고그것을 FormData에 넣으면 값들만 담긴다고 생각하면 된다.

function profileImageUpload(pageUserId, principalId) {

   if(pageUserId != principalId){
      alert("프로필 사진을 수정할 수 없는 유저입니다.");
      return;
   }

   $("#userProfileImageInput").click();

   $("#userProfileImageInput").on("change", (e) => {
      let f = e.target.files[0];

      if (!f.type.match("image.*")) {
         alert("이미지를 등록해야 합니다.");
         return;
      }

      // 서버에 이미지를 전송
      let profileImageForm = $("#userProfileImageForm")[0];
      console.log(profileImageForm);

      // FormData 객체를 이용하면 form 태그의 필드와 그 값을 나타내는 일련의 key/value 쌍을 담을 수 있다.
      let formData = new FormData(profileImageForm);

      $.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(res=>{
         // 사진 전송 성공시 이미지 변경
         let reader = new FileReader();
         reader.onload = (e) => {
            $("#userProfileImage").attr("src", e.target.result);
         }
         reader.readAsDataURL(f); // 이 코드 실행시 reader.onload 실행됨.
      }).fail(error=>{
         console.log("오류", error);
      });


   });
}

 

UserApiController
- 사진데이터도 받기 때문에 MultipartFile도 받는데, html에서의 input 아이디와 똑같은 이름으로 받아야한다. 
- userService에 principalId와 파일정보를 넘긴다.
- 회원사진이 변경되면 세션값이 변경되야하기 때문에 변경된 userEntity를 받아서 세션변경을 해준다.

@RequiredArgsConstructor
@RestController
public class UserApiController {

    private final UserService userService;
    private final FollowService followService;


    @PutMapping("/api/user/{principalId}/profileImageUrl")
    public ResponseEntity<?> profileImageUrlUpdate(@PathVariable int principalId, MultipartFile profileImageFile,
                                                   @AuthenticationPrincipal PrincipalDetails principalDetails){
        User userEntity = userService.profileImageUrlUpdate(principalId, profileImageFile);
        principalDetails.setUser(userEntity); // 세션 변경
        return new ResponseEntity<>(new CMRespDto<>(1, "프로필사진변경 성공", null), HttpStatus.OK);
    }

..


}

 

UserService

@RequiredArgsConstructor
@Service
public class UserService {

    private final UserRepository userRepository;
    private final FollowRepositoy followRepositoy;
    private final BCryptPasswordEncoder bCryptPasswordEncoder;

    @Value("${file.path}") //application.properties에서 가져옴
    private String uploadFolder;

    @Transactional
    public User profileImageUrlUpdate(int principalId, MultipartFile profileImageFile){

        UUID uuid = UUID.randomUUID(); // uuid
        String imageFileName = uuid+"_"+profileImageFile.getOriginalFilename(); // 1.jpg
        System.out.println("이미지 파일이름 : "+imageFileName);

        Path imageFilePath = Paths.get(uploadFolder+imageFileName);

        try {
            Files.write(imageFilePath, profileImageFile.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }

        User userEntity = userRepository.findById(principalId).orElseThrow(()->{
            // throw -> return 으로 변경
            return new CustomApiException("유저를 찾을 수 없습니다.");
        });
        userEntity.setProfileImageUrl(imageFileName);

        return userEntity;

    }

+ Recent posts