https://whyeskang.com/258

 

Postman을 이용한 File, Dto 동시 Post요청

보통 Controller에서 Dto를 받을 때는 @RequestBody를 주로 사용합니다. 그리고 File을 받을 때는 MultipartFile 객체를 사용하며, @RequestParam을 사용합니다. 하지만 File과 Dto를 같이 받기 위해서는 @RequestPart라

whyeskang.com

작년에 이어 File, Dto 동시 요청 2탄입니다.

 

이전 글에서는 단일 File과 Dto를 동시에 요청받았습니다.

이번 글에서는 File과 Dto의 List를 Postman을 이용하여 요청하는 것을 다루려고 합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Entity
@Data
@NoArgsConstructor
public class User {
    @Id
    String userId;
    String password;
    String profileImageUrl;
 
    public User(UserSignUpReq userSignUpReq) {
        this.userId = userSignUpReq.getUserId();
        this.password = userSignUpReq.getPassword();
    }
}
cs

User Entity입니다.

테스트 용도이니 간단하게만 작성해줍니다.

1
2
3
4
5
@Data
public class UserSignUpReq {
    String userId;
    String password;
}
cs

RequestDto 또한 간단하게 해줍니다.

 

 

1
2
3
4
5
6
7
8
9
10
@PostMapping("/signup")
public ResponseEntity<List<UserGetRes>> signUpUser(
       @RequestPart(value = "multipartFileList") List<MultipartFile> multipartFileList,
       @RequestPart(value = "userSignUpReqList") List<UserSignUpReq> userSignUpReqList) {
    return new ResponseEntity<>(
            userService.loginUser(
                    multipartFileList,
                    userSignUpReqList.stream().map(userSignUpReq -> new User(userSignUpReq)).collect(Collectors.toList())),
            HttpStatus.OK);
}
cs

그 다음 요청을 받을 Conrtoller입니다.

어노테이션은 @RequestPart로 이전과 같으며, 요청을 정상적으로 받았는지 확인하기 위해 List<ResDto>를 리턴합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@Override
public List<UserGetRes> loginUser(List<MultipartFile> multipartFileList, List<User> userList) {
    try {
        String separ = File.separator;
        String today = new SimpleDateFormat("yyMMdd").format(new Date());
 
        File file = new File("");
        String rootPath = file.getAbsolutePath().split("src")[0];
        String savePath = rootPath + separ + "profileImage" + separ + today;
        if (!new File(savePath).exists()) {
            try {
                new File(savePath).mkdirs();
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
 
        int len = multipartFileList.size();
        for (int i = 0; i < len; i++) {
            // multipartFileList와 userList의 길이가 무조건 같고, 순서가 일치하다고 가정한다.
            MultipartFile multipartFile = multipartFileList.get(i);
 
            String originFileName = multipartFile.getOriginalFilename();
            String saveFileName = UUID.randomUUID().toString() + originFileName.substring(originFileName.lastIndexOf("."));
 
            String filePath = savePath + separ + saveFileName;
            multipartFile.transferTo(new File(filePath));
 
            userList.get(i).setProfileImageUrl(filePath);
        }
 
        return userRepository.saveAll(userList).stream().map(user -> UserGetRes.of(user)).collect(Collectors.toList());
    }
    catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}
cs

받은 요청을 처리할 Service입니다.

File과 User List의 길이와 순서가 같다고 가정하고 구현한 코드입니다.

중요한건 "File과 User의 List를 같이 받는 것" 입니다.

파일을 지정한 경로에 저장한 후 DB에 추가하는 로직이며, 이전 글에 List만 추가되었습니다.

 

우선 단일 File, Dto 요청 시에는 Body -> form-data에서 File 업로드 및 Dto는 json 방식으로 작성하면 된다고 하였습니다.

 

 

아 맞다 contentType 추가해야하는데

 

Dto 쪽에는 contentType을 application/json으로 맞춰줘야 합니다.

 

 

List를 추가한다고 해서 크게 달라질건 없었습니다.

File은 같은 value로 원하는 수만큼 추가하면 되고,

Dto는 똑같이 json 방식으로 작성해주고, List가 되었으니 대괄호 "[]" 만 추가하면 되겠습니다. (중괄호 "{}" 아닙니다!)

 

이제 Send를 누르면 데이터가 잘 들어가는 것을 확인할 수 있습니다.

 

확인해야할 부분은

Postman에서 입력할 KEY와 @RequestPart의 value로 지정한 값이 일치해야 한다는 것

같은 KEY로 파일을 등록하면 List가 된다는 것

Dto는 form-data에서 json 방식으로 등록해야 하며, List는 대괄호를 추가해야 한다는 것

Dto의 contentType을 application/json으로 맞춰야 한다는 것

정도가 되겠습니다.

 

보통 Controller에서 Dto를 받을 때는 @RequestBody를 주로 사용합니다.

그리고 File을 받을 때는 MultipartFile 객체를 사용하며, @RequestParam을 사용합니다.

 

하지만 File과 Dto를 같이 받기 위해서는 @RequestPart라는 어노테이션이 필요합니다.

File은 @RequestParam, Dto는 @RequestBody를 사용해서 받을려고 했지만 몇번을 시도해도 안되더라고요..

그래서 구글링을 통해 RequestPart라는 어노테이션을 찾아냈습니다.

 

우선 Controller입니다.

File과 Dto 모두 @RequestPart 어노테이션으로 받도록 합니다.

 

그리고 Dto인 UserInsertPostReq는 이렇게 구성되어 있습니다.

이전글 에서 사용했던 Dto와 동일합니다.

 

그리고 Controller에서 호출할 Service의 insertUser 메소드입니다.

파일을 저장할 경로를 지정한 후에 지정한 경로에 파일을 저장하고 DB에 유저 정보를 추가하는 로직입니다.

 

저는 이를 수행하기 위해 포스트맨을 사용하였습니다.

Key name은 @RequestPart 에서 value로 지정해준 name과 동일한 Key name으로 넣어줍니다.

이제 저기있는 Send를 눌러볼까요?

 

네 역시나 400에러가 발생합니다.

 

구글링을 통해 value에 json형식으로 넣는 방법을 알게되었고, 그대로 따라해보았습니다.

이런식으로 Key name은 userInsertPostReq, value는 json 방식으로 작성하였습니다.

다시 Send를 눌러보겠습니다.

 

이번에는 415 에러가 발생합니다..

 

한 두 시간 동안은 400, 415에러만 봤던것 같습니다.

 

이 에러들을 해결하기 위해 구글링을 해본 결과로는

여기서 Dto인 userInsertPostReq는 content type을 application/json으로 지정하면 해결할 수 있습니다.

userInsertPostReq의 content type을 application/json으로 지정한 후 Send를 누릅니다.

 

그럼 입력한 정보가 잘 들어가는 것을 확인할 수 있습니다.

 

File과 Dto를 같이 받아올 때 Key name과 content type 설정을 잘못하여 나온 에러 상황이었습니다.

이 방법 외에 다른 방법이 있는지는 잘 모르겠습니다. 더 많은 공부가 필요할 것 같습니다.

 

지금까지 단일 File과 Dto를 요청하는 것에 대해 알아보았고, 다수의 File과 Dto 요청에 관해서는 아래 링크에서 확인하시면 됩니다.

https://emoney96.tistory.com/375

 

Postman을 이용한 다수의 File, Dto 동시 Post 요청

https://emoney96.tistory.com/258 Postman을 이용한 MultipartFile, Dto 동시 Post요청 보통 Controller에서 Dto를 받을 때는 @RequestBody를 주로 사용합니다. 그리고 File을 받을 때는 MultipartFile 객체를 사..

emoney96.tistory.com

 

+ Recent posts