base64를 이용한 데이터 송수신

merci·2023년 3월 27일
0

Rest Api 프로젝트

목록 보기
5/6

base64 with json

파일 송수신을 할때 base64로 인코딩된 파일을 송수신해서 서버에서 디코딩후 처리를 하려고 한다.
일반적으로 데이터를 송수신할때는 json을 이용하기 때문에 base64로 변환된 데이터 또한 json으로 보내게 된다.


인코딩후 json으로 전송

데이터를 인코딩하는 방식은 여러 방식이 있기때문에 하나의 예를 이용한다.

void main() {
  String text = 'Hello, world!';
  
  // Encoding to base64
  String encoded = base64.encode(utf8.encode(text));
  print(encoded); // '인코딩된 코드"
  
  // Decoding from base64
  String decoded = utf8.decode(base64.decode(encoded));
  print(decoded); // "Hello, world!"
}

이를 이용해서 사진데이터를 base64로 인코딩후 json에 담으면 아래처럼 된다.

{
    "fileName": "test3.jpg",
    "photo": "data:image/jpeg;base64,/9j/4A.... 이하 생략
}

처리를 쉽게 하기 위해서 파일이름은 따로 저장했다.

이제 서버에서는 json을 받게 되는데 아래처럼 받는다
먼저 데이터를 받을 오브젝트를 하나 만들고

public class PhotoReq {
    
    @Getter @NoArgsConstructor
    public static class PhotoUpdateDto{
        private String fileName;
        private String photo;

        @Builder
        public PhotoUpdateDto(String fileName, String photo) {
            this.fileName = fileName;
            this.photo = photo;
        }
    }
}

매핑된 메소드에서 json을 받도록 설정한다.
이번에는 @Valid로 유효성 검사를 하지않고 간단하게 한줄만 추가했다.

    @PutMapping("/comp/profileUpdate")
    public  ResponseEntity<?> profileUpdate(@RequestBody PhotoUpdateDto pDto) {
        CheckValid.inNullApi(pDto.getPhoto(), "사진이 전송 되지 않았습니다.");
        
        String result = compService.프로필사진수정(pDto, comp.getId());
        CompUpdatePhotoOutDto update = CompUpdatePhotoOutDto.builder()
                .compId(comp.getId())
                .photo(result)
                .build();
        return new ResponseEntity<>(new ResponseDto<>(1, "프로필 수정 성공", update), HttpStatus.OK);
    }

서비스에서는 아래의 로직을 이용하게 된다.

    @Transactional
    public String 프로필사진수정(PhotoUpdateDto pDto, Integer compId) {

        String uuidImageName = PathUtil.writeImageFile2(pDto.getPhoto(), pDto.getFileName());

        Comp compPS = compRepository.findByCompId(compId);
        compPS.setPhoto(uuidImageName);
        try {
            compRepository.updatePhotoById(uuidImageName, compId);
        } catch (Exception e) {
            throw new CustomException("사진 수정에 실패 했습니다.", HttpStatus.INTERNAL_SERVER_ERROR);
        }
        return uuidImageName;
    }


base64 디코딩 및 저장

PathUtil은 유틸클래스로서 아래의 코드를 가지고 있다.

public class PathUtil {

    static String realFileName = null ;

    private static String getStaticFolder() { // 사진을 저장할 경로
        return System.getProperty("user.dir") + "\\src\\main\\resources\\static\\";
    }

    public static String writeImageFile2(String base64EncodedImage, String fileName){
        byte[] imageBytes = Base64.getDecoder().decode(base64EncodedImage.split(",")[1]);
        
        UUID uuid = UUID.randomUUID();
        String uuidImageDBName = "/images/" + uuid + "_" + fileName;
        String uuidImageRealName = "\\images\\" + uuid + "_" + fileName;
        String staticFolder = getStaticFolder();
        Path imageFilePath = Paths.get(staticFolder + "\\" + uuidImageRealName);
        
        try {
            Files.write(imageFilePath, imageBytes); 
        } catch (Exception e) {
            throw new CustomException("사진을 웹서버에 저장하지 못하였습니다.", HttpStatus.INTERNAL_SERVER_ERROR);
        }
        return uuidImageDBName;


    }
}

여기서

byte[] imageBytes = Base64.getDecoder().decode(base64EncodedImage.split(",")[1]);

split() 으로 jpeg;base64를 분리시키고 base64로 인코딩된 데이터를 디코딩한다.
사진은 바이너리 데이터이므로 바이트배열에 저장한다.

사진의 이름이 중복될 수 있으므로 랜덤한UUID를 생성 후 앞에 붙이고 저장한다.
uuidImageDBName를 리턴해서 DB에는 저장한 사진의 경로를 넣는다.

클라이언트가 사진을 요청하면 DB에 저장된 사진의 경로만 반환해주면 된다.

사진 저장후 응답받은 데이터

profile
작은것부터

0개의 댓글