Spring 파일과 이미지 데이터를 한번에 요청 / 응답하기

5tr1ker·2022년 12월 6일
1

Spring 성능 최적화

목록 보기
1/1
post-thumbnail

요청

Server

@RequestMapping(value = "/post" , method = RequestMethod.POST , consumes = {MediaType.APPLICATION_JSON_VALUE , MediaType.MULTIPART_FORM_DATA_VALUE})
	public 리턴타입 addPost(@RequestPart(value="request") PostDTO postData , @RequestPart(value="image") MultipartFile imgFile 
			, HttpServletRequest request) throws IllegalStateException, IOException {
		int number = postService.addPost(postData , imgFile);
		return 리턴값
	}
  • @RequestMapping의 인자로 consumes 을 JSON 정보와 , File이라는 뜻의 MediaType.APPLICATION_JSON_VALUEMediaType.MULTIPART_FORM_DATA_VALUE 를 넣어줍니다.
  • 두개의 데이터를 받아야 하기 때문에 Client에서 각각 키값으로 넘겨준 데이터를 분류하기 위해 @RequestPart 으로 데이터를 분류해 줍니다.
  • 각각 분류된 데이터로 JSON 으로 전달 받은 DTO 파일과 , File 정보를 담은 MultipartFile 를 Service에서 적절하게 활용해 주세요.

Client

postMan

필자는 Front-end에 대한 정보가 부족해서 간단하게 Postman 으로 요청하는 방법을 보여줍니다.

  • form-data 방식으로 Key와 Value로 값을 삽입해주세요.
  • Key값은 Service에서 @RequestPart(value = 값) value 값과 같은 키 값을 넣어주세요.
  • JSON의 경우 사진과 같이 {"key" : "value"} 형식으로 넣어주세요.
  • Content-type은 Json 또는 image 확장자에 맞게 설정해주세요.
  • Image의 경우 PostMan 기준 키 입력하는 곳 오른쪽에 마우스를 올리면 드롭 박스 가 나타나는데 거기에 File을 선택해주세요.

React

React의 경우 두가지 파일을 전송해야 하기 때문에 formData 를 사용해 주셔야합니다.

let userForm = new FormData();
    const datas = {
      title : postInfo.title ,
      description: postInfo.description
    }
    userForm.append('image', image);
    userForm.append("request", new Blob([JSON.stringify(datas)], { type: "application/json" }));
    axios
      .post(`/post/post`, userForm , {
        headers: { 
          Authorization : getAccessToken()
        }
      })

먼저 FormData'키' 와 '값' 형태로 append해줍니다. 이미지 같은 경우에 그냥 넣어도 되지만 JSON 같은 경우에는 서버에서 값을 읽어야 하기때문에 JSON 으로 형 변환을 시켜주셔야 합니다.

응답

Server

서버의 경우 JSON 과 Image를 동시에 전송해야 하는데 해당 포스트는 image를 Base64 로 변환해서 전송하는 방식 사용합니다.

public List<PostDTO> getAllPost(Pageable pageable) {
    HttpHeaders header = new HttpHeaders();
	File imageFile;
    imageFile = new File(fileDir + data.getThumbnail()); // 해당 이미지 파일을 엽니다.
  		try {
				if(Files.probeContentType(imageFile.toPath()) != null) header.set("Content-Type" , Files.probeContentType(imageFile.toPath()));
				data.setImage(new ResponseEntity<byte[]>(FileCopyUtils.copyToByteArray(imageFile) , header , HttpStatus.OK));
			} catch (IOException e) { // 썸네일이 없을 때
				data.setImage(null);
			}
  }
  • File 로 이미지 파일을 엽니다.
  • probeContentType 메소드를 이용해서 해당 파일의 확장자를 이용해 마임타입 을 확인 후 header 에서 전송할 데이터의 마임타입을 지정해 줍니다.
  • new ResponseEntity<byte[]>() 를 이용해서 이미지 파일을 Base64 로 반환합니다.
  • 이후 반환 받은 값을 DTO나 MAP을 이용해서 전송해줍니다.

데이터 처리

Cilent

서버에서 위와 같이 byte 타입으로 전송한 데이터는 클라이언트에서 Base64로 변환해 주면 됩니다. 이후 클라이언트에서 src 경로에 넣어주면 되나 앞에 data:image/;base64, 를 붙여 넣어주셔야합니다.

예 ) React의 경우

  <img src={"data:image/;base64,[파일명]" + imageTest} width='120' height='120' alt='testA'></img>
profile
https://github.com/5tr1ker

0개의 댓글