[Spring] 이미지를 파일로 저장하지 않고 업로드 하기

이멀젼씨

·

2023. 3. 20. 20:12

목적

이미지 업로드 시 이미지를 디스크에 저장하지 않기 위함

목차

  1. 서론
  2. 구현 방법
  3. 이미지 다운로드
  4. 이미지 업로드

1. 서론

회사에서 외부 상품을 크롤링하여 내부 상품으로 변환하는 프로세스를 개발중이었다.

배치 어플리케이션을 통해 외부 상품의 이미지를 회사 이미지 서버에 올리고, 회사 이미지 서버의 url을 DB에 저장해야 했다.

배치 어플리케이션이기 때문에 메모리 관리가 크게 중요하지 않았고,

(쿠버네티스의 새로운 Pod에 어플리케이션이 뜨고 죽기 때문, 새로운 배치 어플리케이션은 새로운 Pod에서 시작)

굳이 디스크에 저장하고 싶지 않았다.(그냥 메모리에서 처리하고 싶었다.)

2. 구현 방법

이미지 url에 접근하여 이미지의 정보를 ByteArray형태로 가져온다.

ByteArray타입의 데이터를 ByteArrayResource의 파라미터로 주어 메모리에 리소스 형태로 로딩한다.

(일반 파일을 읽었을 때와 동일하게 리소스를 메모리에 로딩)

이후 파일 업로드를 할 때 해당 리소스를 파라미터로 넣어 서버로 전송한다.

3. 이미지 다운로드

restTemplate을 통해 이미지 url에 접근하여 반환값을 ByteArray형태로 받아온 뒤 이를 ByteArrayResource의 형태로 변경한다.

파일의 확장자를 가져온 이유는 파일 업로드 시 파일의 풀네임이 필요하기 때문이다.

(파일의 확장자를 붙이지 않으면 파일 업로드 시 이미지 서버에서 업로드된 파일이 이미지임을 인식하지 못한다.)

fun downloadImageFromUrl(url: String): ByteArrayResource {
    return try {
        val imageByteArray = restTemplate.getForObject(url, ByteArray::class.java)
        val extension = getFileExtension(imageByteArray!!)

        val imageByteArrayResource = object : ByteArrayResource(imageByteArray!!) {
            override fun getFilename(): String {
                return "temp" + extension
            }
        }

        imageByteArrayResource
    } catch (e: Exception) {
        //Error Handling
    }
}

private fun getFileExtension(byteArray: ByteArray): String? {
    val inputSteam = ByteArrayInputStream(byteArray)
    val mimeType = URLConnection.guessContentTypeFromStream(inputSteam)
    val extension = mimeTypes.forName(mimeType).extension
    inputSteam.close()
    return extension
}

4. 이미지 업로드

fun uploadImageToImageCdn(byteArrayResource: ByteArrayResource): ImageUploadResponse {
    try {
          headers.contentType = MediaType.MULTIPART_FORM_DATA

        val body = LinkedMultiValueMap<Any, Any>()
        body.add(FILES, byteArrayResource)

        val requestEntity = HttpEntity(body, headers)

        val response = restTemplate.exchange(
            getImageUploadUrl(),
            HttpMethod.POST,
            requestEntity,
            ImageUploadResponse::class.java
        )

        response
    } catch (e: Exception) {
        //Error Handling
    }
}

이미지 업로드 시엔 미디어 타입을 multipart/form-data로 지정해 주고, ByteArrayResource객체를 body에 넣어 전송하면 된다.