웹플럭스에서 파일을 받고 보내는 것은 어렵지가 않습니다.
만약 파라미터가 존재하는 경우가 생긴다면 방법이 조금 복잡합니다.
먼저 request객체를 살펴보아야 합니다.
아래 코드는 파일을 사용자가 업로드를 할 때 사용하는 코드의 예제 입니다.
@Bean
public RouterFunction<ServerResponse> fileUpload() {
RequestPredicate predicate = RequestPredicates.POST("/fileUpload").and(RequestPredicates.accept(MediaType.MULTIPART_FORM_DATA));
RouterFunction<ServerResponse> response = RouterFunctions.route(predicate, (request)->{
Mono<String> mapper = request.multipartData().map(it -> it.get("files"))
.flatMapMany(Flux::fromIterable)
.cast(FilePart.class)
.flatMap(it -> it.transferTo(Paths.get("/저장경로/" + it.filename())))
.then(Mono.just("OK"));
Mono<ServerResponse> res = ServerResponse.ok().contentType(MediaType.TEXT_PLAIN).body(BodyInserters.fromProducer(mapper, String.class));
return res;
});
return response;
}
사용자가 fileUpload라는 주소를 통해서 name값을 files로 보낸 경우 입니다.
여기서 대부분 사람들은 multipart 방식으로 보낸 파라미터를 받기 위해 아래처럼 사용합니다.
@Bean
public RouterFunction<ServerResponse> fileUpload() {
RequestPredicate predicate = RequestPredicates.POST("/fileUpload").and(RequestPredicates.accept(MediaType.MULTIPART_FORM_DATA));
RouterFunction<ServerResponse> response = RouterFunctions.route(predicate, (request)->{
request.queryParams(); //이러한 방식으로 시도를 해 봅니다..
Mono<String> mapper = request.multipartData().map(it -> it.get("files"))
.flatMapMany(Flux::fromIterable)
.cast(FilePart.class)
.flatMap(it -> it.transferTo(Paths.get("/저장경로/" + it.filename())))
.then(Mono.just("OK"));
Mono<ServerResponse> res = ServerResponse.ok().contentType(MediaType.TEXT_PLAIN).body(BodyInserters.fromProducer(mapper, String.class));
return res;
});
return response;
}
리퀘스트 객체의 파라미터를 가져오는 메소드queryParmas입니다.
해당 메소드는 일반적인 요청에 대해서는 응답하지만 이미 Request객체가 Multipart 형식으로 된 경우에는 아무런 값을 주지 않습니다.
빈 값만 있다고 나올 뿐 입니다..ㅠ
request객체의 multipartData 메소드를 이용해야만 파일과 같이 보낸 파라미터를 받을 수 있습니다.
multipartData 메소드를 통해서 받는 데이터는 Mono객체에 키 값은 String, 데이터는 List형식의 Part 라는 객체로 구성되어 있습니다.
Part는 인터페이스의 일종 입니다.
그러면 간단하게 데이터를 출력하여 보겠습니다.
위 forEach부분에서 key는 일반 문자열로, value는 List형식의 Part 인터페이스로 구성되어 있습니다.
이를 반복문을 통해서 key 와 value를 출력 해 보았습니다.
전송한 데이터는,
key값 files를 통해서 파일 2개를 전송하였습니다.
그리고 param_same이라는 이름으로 값 2개를, param1, param2로 각각 데이터를 전송 해 보았습니다.
여기서 조건문을 통해서 파일을 저장하는 부분과, value를 가져오는 부분을 분리하여 보겠습니다.
public Mono<ServerResponse> fileData(ServerRequest request){
Mono<String> then = request.multipartData().map(it-> {
it.forEach( (arg1, arg2)->{
if(!arg1.equals("files")) { //파일이 아니면
arg2.forEach( body->{
body.content().subscribe(dataBuffer -> {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
DataBufferUtils.release(dataBuffer);
String valueFromMultipart = new String(bytes, StandardCharsets.UTF_8);
System.out.println("key : "+ arg1+", I'm data : "+valueFromMultipart);
});
});
} else { //파일이면,
System.out.println("key : "+ arg1+", I'm file : "+arg2);
Mono.just(it.get("files")).flatMapMany(Flux::fromIterable)
.cast(FilePart.class)
.flatMap( file -> {
return file.transferTo(Paths.get("E:/git/" + file.filename()));
}).subscribe();
}
});
return it;
}).then(Mono.just("OkOk"));
return ServerResponse.ok().body(then, String.class).onErrorResume(e -> Mono.error(new RuntimeException(e.getMessage())) );
}
body는 Part 인터페이스이며 content라는 메소드를 통해서 값을 받게하였습니다.
그리고 subscribe를 통해서 내부의 코드가 동작하게 하였습니다.
파일을 저장하는 부분은 이전내용과 동일합니다.
여기서 valueFromMultipart 의 값이 바로 전송한 데이터를 문자로 변형한 값을 의미 합니다.
이상으로 웹플럭스에서 멀티파트 형식의 요청에서의 파라미터를 받는 방법에 대해서 살펴 보았습니다.
spring webflux!
* 내용을 채우고 수정중입니다.
* 튜토리얼이나 가이드 목적보다도 개념정리에 목적을 두고 쓰고있습니다. 틀린부분이나 누락된 부분은 꼭 알려주세요!
'Spring framework > Spring Webflux' 카테고리의 다른 글
[webflux websocket broad cast all] 웹플럭스 웹소켓 에코 말고 전체에게 보내기 (0) | 2023.05.22 |
---|---|
spring webflux 9 (웹플럭스 적용기, AOP) (3) | 2020.04.10 |
spring webflux 8 (웹플럭스 적용기, 웹 필터, 인터셉터) (2) | 2020.04.06 |
spring webflux 7 (웹플럭스 적용기, MongoDb) (0) | 2020.04.01 |
spring webflux 6 (웹플럭스 적용기, Mysql) (0) | 2020.03.30 |
댓글