글을 쓸 당시에는 직접 구현했던 것을 토대로 작성했는데, 현재는 그럴 수가 없어 업데이트를 하지 못했습니다.
변경사항이 있다고 하니 유의 바랍니다.
Multipart
Retrofit2을 통해 서버로 파일을 전송할 때 사용하게 된다.
아마 다음과 같은 형태로 인터페이스를 정의할 것이다.
@Multipart
@POST("api주소")
Call<SomeResponse> request(파라미터들...);
파일 전송때문에 Multipart 어노테이션이 붙어서, 그냥 보낼 수 있는 타입도 Multipart에 맞게 보내야 했던 것 같다.
왜그랬는지 기억은 안나는데, file 전송할 때 자꾸 안돼서 이것저것 계속 시도했었던 것 같다.
일단 내 경우에 성공적으로 동작했던 방법을 정리한다.
file이 아닌 것
단일 항목
한개만 보내면 되는 경우, `RequestBody`를 사용하면 된다.
@Multipart
@POST("api주소")
Call<SomeResponse> request(@Part("key") RequestBody param);
`RequestBody`는 다음과 같이 만들 수 있다.
String text = "some text";
RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain"), text);
위 코드는 String을 담기 때문에 MediaType을 "text/plain"으로 지정해줬다.
여러 단일 항목을 모아서 보내기
단일 항목이 많아서 파라미터를 구구절절 쓰기 싫을 때는 `Map`으로 모아서 보낼 수 있다.
@Multipart
@POST("api주소")
Call<SomeResponse> request(@PartMap Map<String, RequestBody> params);
다음과 같이 `Map`을 만들 수 있다.
RequestBody nameBody = RequestBody.create(MediaType.parse("text/plain"), "철수");
RequestBody ageBody = RequestBody.create(MediaType.parse("text/plain"), "15살");
RequestBody emailBody = RequestBody.create(MediaType.parse("text/plain"), "chulsu@email.com");
HashMap<String, RequestBody> requestMap = new HashMap<>();
requestMap.put("name", nameBody);
requestMap.put("age", ageBody);
requestMap.put("email", emailBody);
`put`에 들어가는 String은 서버에서 받는 key값? 필드아이디?가 되겠다.
같은 항목을 여러개 보내기
같은 항목에 대해서 배열로 보내야 할 경우 `List`를 사용한다.
하지만 `RequestBody`를 사용하지 않고, `MultipartBody.Part`를 사용한다.
@Multipart
@POST("api주소")
Call<SomeResponse> request(@Part List<MultipartBody.Part> params);
`List<MultipartBody.Part>`는 다음과 같이 만들 수 있다.
ArrayList<MultipartBody.Part> names = new ArrayList<>();
names.add(Multipart.Part.createFormData("이름", "철수");
names.add(Multipart.Part.createFormData("이름", "제임스");
names.add(Multipart.Part.createFormData("이름", "존");
// 계속 추가...
file인 것
단일 file
그냥 `MultipartBody.Part` 형태로 보내면 된다.
@Multipart
@POST("api주소")
Call<SomeResponse> request(@Part MultipartBody.Part file);
file을 담는 `MultipartBody.Part`는 다음과 같이 만든다.
나는 사진을 보냈어야 했기 때문에 예시도 사진을 보내는 경우를 썼다.
// Uri 타입의 파일경로를 가지는 RequestBody 객체 생성
RequestBody fileBody = RequestBody.create(MediaType.parse("image/jpeg"), Uri filePath);
// RequestBody로 Multipart.Part 객체 생성
MultipartBody.part filePart = Multipart.Part.createFormData("photo", "photo.jpg", fileBody);
`createFormData(...)`에 들어가는 파라미터는 순서대로 다음과 같은 의미를 가진다.
- 서버에서 받는 키값 String
- 파일 이름 String
- 파일 경로를 가지는 RequestBody 객체
여러개의 file
같은 key값으로 여러항목을 보낼 때 처럼 `List`를 사용한다.
@Multipart
@POST("api주소")
Call<SomeResponse> request(@Part List<MultipartBody.Part> files);
file을 담는 `List<MultipartBody.Part>`는 다음과 같이 만들 수 있다.
// 여러 file들을 담아줄 ArrayList
ArrayList<MultipartBody.Part> files = new ArrayList<>();
// 파일 경로들을 가지고있는 `ArrayList<Uri> filePathList`가 있다고 칩시다...
for (int i = 0; i < filePathList.size(); ++i) {
// Uri 타입의 파일경로를 가지는 RequestBody 객체 생성
RequestBody fileBody = RequestBody.create(MediaType.parse("image/jpeg"), filePathList.get(i));
// 사진 파일 이름
String fileName = "photo" + i + ".jpg";
// RequestBody로 Multipart.Part 객체 생성
MultipartBody.part filePart = Multipart.Part.createFormData("photo", fileName, fileBody);
// 추가
files.add(filePart);
}
단일 file처럼 똑같이 `RequestBody` 만들고, 그걸로 `MultipartBody.Part` 만든 다음,
`ArrayList<MultipartBody.Part>`에 넣어주기만 하면 된다.
끝
이것때문에 아주 머리가 아팠다.
자꾸 안되는데, 사람마다 방법이 아예 다른것도 아니고 찔끔찔끔 다르고, file이 아닌걸 보내는 방법과... file인데 한개만 보내는 방법과... 여러개를 보내는 방법 등이 다 정리되어 있는 글도 없어서 더 복잡했다.
'Android' 카테고리의 다른 글
[Android] 멀티모듈에서 gradle의 BuildType 공통화 (2) | 2025.06.12 |
---|---|
[Android] java.lang.ClassCastException (0) | 2025.06.12 |
[Android] Compose TextField 커스텀 (2) | 2025.06.12 |
[Android] LazyColumn안에 LazyVerticalGrid 넣기(nested scroll) (0) | 2025.06.12 |
[Android] RecyclerView와 ListAdapter (Java) (1) | 2025.06.12 |