Joshua게시판(SSR)-15-사진업로드 UUID

jaegeunsong97·2023년 8월 15일
0

SSR 기반 JoshuaBlog

목록 보기
15/23
post-thumbnail

깃허브링크

노션링크

  • header.jsp

404, static에 upload라는 폴더가 존재하지 않아서

따라서 static 내부가 아닌 외부의 upload 폴더를 찾게 바꿔주기

  • 경로 바꾸는 등록 코드
package coffee.pastry.joshuablog.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.resource.PathResourceResolver;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

     @Override
     public void addResourceHandlers(ResourceHandlerRegistry registry) {
          WebMvcConfigurer.super.addResourceHandlers(registry);

          registry.addResourceHandler("/upload/**") // 이렇게 오면
                    .addResourceLocations("file:" + "./upload/") // 이거를 찾을께
                    .setCachePeriod(60 * 60) // 1시간
                    .resourceChain(true)
                    .addResolver(new PathResourceResolver());
     }

}

  • profileUpdateForm 코드

  • header.jsp

sessionUser 이부분은 로그인하고 강제로 1개더 만든 것

  • updateProfile 화면 분석

선택된 파일 없음 이 부분이 변하게 되면 chooseImage발동

<script>
    function chooseImage(obj){
        //console.log(obj);
        //console.log(obj.files);
        let f  = obj.files[0];
        if(!f.type.match("image.*")){ // MIME validation
            alert("이미지를 등록해야 합니다.");
            return;
        }
        let reader = new FileReader(); 
        reader.readAsDataURL(f); // IO 발생 (내부적으로 Promise 처리)
        // 콜스택이 다 비워지고, 이벤트 루프로 가서 readAsDataURL 이벤트가 끝나면 콜백시켜주는 함수
        reader.onload = function (e){ // 할일이 없을 떄 function 발동 -> 파일 다 읽었나 -> check
            console.log(e);
            console.log(e.target.result);
            $("#imagePreview").attr("src", e.target.result); // 읽은 사진을 바꿔지치
        } 
    }
</script>

  • userController
@PostMapping("/s/user/{id}/updateProfile")
     public String profileUpdate(
               @PathVariable Long id,
               MultipartFile profile,
               @AuthenticationPrincipal MyUserDetails myUserDetails) {
          if (id != myUserDetails.getUser().getId()) {
               throw new Exception403("권한이 없습니다");
          }

          if (profile.isEmpty()) {
               throw new Exception400("profile", "사진이 전송되지 않았습니다");
          }

          User userPS = userService.프로필사진수정(profile, id);

          myUserDetails.setUser(userPS);
          session.setAttribute("sessionUser", userPS);

          return "redirect:/";
     }

  • MyFileUtil
package coffee.pastry.joshuablog.core.util;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;

import org.springframework.web.multipart.MultipartFile;

import coffee.pastry.joshuablog.core.exception.ssr.Exception500;

public class MyFileUtil {

     public static String write(String uploadFolder, MultipartFile file) {
     	  // 롤링기법 (사진명 : 랜덤_사진이름.png)
          UUID uuid = UUID.randomUUID();
          String originalFilename = file.getOriginalFilename();
          String uuidFilename = uuid + "_" + originalFilename;
          try {
          	   // 파일 사이즈 줄이기
               Path filePath = Paths.get(uploadFolder + uuidFilename);
               Files.write(filePath, file.getBytes());
          } catch (Exception e) {
               throw new Exception500("파일 업로드 실패 : " + e.getMessage());
          }
          return uuidFilename;
     }
}

UUID -> 랜덤값(난수),

  • userService

@Transactional
     public User 프로필사진수정(MultipartFile profile, Long id) {
          try {
               String uuidImageName = MyFileUtil.write(uploadFolder, profile);

               User userPS = userRepository.findById(id)
                         .orElseThrow(() -> new Exception500("로그인 된 유저가 DB에 존재하지 않음"));
               userPS.changeProfile(uuidImageName);
               return userPS;
          } catch (Exception e) {
               throw new Exception500("프로필 사진 등록 실패 : " + e.getMessage());
          }
     } // 더티채킹(업데이트)
  • application-dev

return을 받고 세션 동기화(컨트롤러), 왜냐하면 사진이 바뀌었으니까 동기화 떄문에

세션 2개 동기화(SecurityContextHolder의 UserDetails랑 내가 강제로 만든 session 동기화)

왜 2개를 동기화?? -> 내가 강제로 만든 세션은 VIEW 까지 들고가야하니까!!

  • 테스트

  • header.jsp 변경

profile
현재 블로그 : https://jasonsong97.tistory.com/

0개의 댓글