안드로이드 앱을 개발하며 서버와 네트워크 작업을 하는 일이 종종 있습니다.
Get요청이나 Post요청 등 여러 요청을 보낼 때 단순히 텍스트로 정보를 보내는 것이 아닌
이미지를 보낼 때 어떻게 해야 할지 설명해 보겠습니다.
단순히 정보를 보내기 위해서 gradle을 추가하거나, internet 관련 권한이나
서버 통신을 위한 작업들은 이번 글에서 주로 다루는 주제가 아니므로
다른 글에서 제대로 설명하겠습니다.
먼저 서버로 이미지를 업로드할 때에는 주로 이미지를 파일로 전송합니다.
Retrofit에서는 편리하게 이미지를 전송할 수 있도록 지원해 줍니다.
api 관련 로직 작성
import okhttp3.MultipartBody
import retrofit2.http.Multipart
import retrofit2.http.POST
import retrofit2.http.Part
interface ImageAPI {
@Multipart
@POST("API 주소")
fun postImage(
@Part file: List<MultipartBody.Part>
): ImageResponse
}
Retrofit을 사용하기 위해 API를 인터페이스로 작성해 줍니다.
위 코드에서
@Multipart
@POST("API 주소")
fun postImage(
@Part file: List<MultipartBody.Part>
): ImageResponse
이미지를 실제로 업로드하는 부분인 이 요청에서 자세히 봐야 할 부분은
@Multipart 어노테이션과 @Part, MultipartBody.Part입니다.
그전에 반환값은 Call이나 Response 등으로 반환값을 다른 방법으로 받을 수도 있습니다.
Multipart
어노테이션은 해당 요청이 파일을
데이터를 여러 부분으로 나눠서 보내는 것입니다.
파일로 데이터를 보내기 위해 어노테이션을 작성해 주었습니다.
Part
Multipart로 나누어준 부분에서 각 파트들을 생성해 줍니다.
MultipartBody.Part
Form Data로 file을 서버로 보내주기 위해 지원해 주는
타입입니다.
만약에 이미지 말고도 다른 데이터도 전송하고 싶다면
@Multipart
@POST("API 주소")
fun postImage(
@Part file: List<MultipartBody.Part>,
@Part id: String
): ImageResponse
이런 식으로 Part를 더 지정해 주면 됩니다.
FormData 생성하기
그리고 해당 코드를 사용하는 부분에서 Form Data를 생성해 주면 됩니다.
방법은 파일 형식으로 생성하고,
파일로 RequestBody를 생성하고,
RequestBody로 MultipartBody를 생성할 수 있습니다.
말로는 조금 이해가 안 될 수 있기에 코드로 확인해 보겠습니다.
private val getContent =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == Activity.RESULT_OK) {
val imageUrl = it.data?.data
val file = File(getPathFromUri(imageUrl))
val requestFile = RequestBody.create("image/*".toMediaTypeOrNull(), file)
val img = MultipartBody.Part.createFormData("files", file.name, requestFile)
postImage(img)
}
}
위 코드는 갤러리에 이미지를 가져와서 Path로 file을 생성해 줍니다.
getPathFromUri와 같은 코드는 이미지의 경로를 가져오기 위해 따로 작성한 함수입니다.
해당 create 함수를 보면 @Deprecated 되어 사용을 권하지는 않지만
MediaType를 지정해 주고, File을 파라미터로 넘겨주면
RequestBody 타입으로 반환해 줍니다.
그러면 해당 requestBody를 가지고, name과 filename을 받아서 Part로 만들어줍니다.
여기서 name은 api를 보낼 때의 name을 뜻하고,
fileName은 서버에 올라갈 이미지의 이름을 뜻합니다.
그 후에 반환된 값이 서버로 넘어갑니다.
마무리
해당 포스트에서는 이미지를 갤러리에서 가져오는 과정이나 retrofit 기본기와 같은 내용은 다루지 않았습니다.
해당 내용들은 다음에 따로 정리해서 올리도록 하겠습니다.
'Android' 카테고리의 다른 글
Composable 에서 ViewModel 공유하기 (0) | 2023.02.19 |
---|---|
[Android] - ConstraintLayout 장점 (0) | 2023.02.17 |
[Android] - Activity의 라이프 사이클 (0) | 2023.02.15 |
[Android] - Android Studio에서 SVG 파일 사용하기 (0) | 2023.02.15 |
[Android] - View와 ViewGroup란 무엇일까 (0) | 2023.02.11 |