diff --git a/src/docs/message-examples/file-from-sam-to-defree.json b/src/docs/message-examples/file-from-sam-to-defree.json new file mode 100644 index 0000000..d563abd --- /dev/null +++ b/src/docs/message-examples/file-from-sam-to-defree.json @@ -0,0 +1,22 @@ +{ + "sender": { + "host-id": "sam", + "timestamp": 1750643945523 + }, + "message-uuid": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6e", + "message-type": "SAVE_FILE", + "recipient": { + "host-id": "defree", + "drop-box-id": "receive-work-image-file" + }, + "data": [ + { + "file-name": "v1.jpg", + "meta-data": { + "FILE_ID": "F1V1JPG", + "ORIGINAL_FILE_NAME": "현장사진1.jpg" + }, + "meta-drop-box-id": "save-work-image-file-info" + } + ] +} diff --git a/src/docs/settings-examples/dfxagent.json b/src/docs/settings-examples/dfxagent.json index c117245..f5566df 100644 --- a/src/docs/settings-examples/dfxagent.json +++ b/src/docs/settings-examples/dfxagent.json @@ -47,6 +47,12 @@ "drop-box-id": "receive-work-image-file", "task-type": "RECEIVE_FILE", "save-directory-root": "D:\\projects\\bsm-lab\\dfx\\run\\receive_file" + }, + { + "drop-box-id": "save-work-image-file-info", + "task-type": "SAVE_DATA_TABLE", + "dataSourceId": "dfcms", + "sql-id": "dfcms.file.insertFileInfo" } ] }, diff --git a/src/main/java/com/bsmlab/dfx/agent/listener/ListenerController.java b/src/main/java/com/bsmlab/dfx/agent/listener/ListenerController.java index 0b1b1e6..50b5056 100644 --- a/src/main/java/com/bsmlab/dfx/agent/listener/ListenerController.java +++ b/src/main/java/com/bsmlab/dfx/agent/listener/ListenerController.java @@ -3,13 +3,18 @@ package com.bsmlab.dfx.agent.listener; import com.bsmlab.dfx.agent.listener.dto.AckDto; import com.bsmlab.dfx.agent.listener.service.ListenerService; import com.bsmlab.dfx.agent.support.ServletUtils; +import com.bsmlab.dfx.agent.support.exception.IllegalMessageException; +import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.Part; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; +import java.util.Collection; +import java.util.Iterator; @Slf4j @RestController @@ -26,9 +31,17 @@ public class ListenerController { public AckDto listener(HttpServletRequest request) { AckDto ackDto = AckDto.builder().build(); try { - String bodyString = ServletUtils.getBodyString(request); - ackDto = listenerService.receiveMessage(bodyString); - } catch (IOException e) { + String contentType = request.getContentType(); + if(contentType != null && contentType.contains("application/json")) { + String bodyString = ServletUtils.getBodyString(request); + ackDto = listenerService.receiveMessage(bodyString); + } + else if(contentType != null && contentType.contains("multipart/form-data")) { + //TODO 파일 전송인 경우 Multipart로 전송하며 파일의 메타데이터인 application/json 과 n개의 파일 본문인 File Multipart 를 합쳐서 전송한다. + Collection parts = request.getParts(); + ackDto = listenerService.receiveFiles(parts); + } + } catch (IOException | ServletException e) { ackDto.setResult(AckDto.ResultType.RECEIVE_FAIL); ackDto.setResultText(e.getMessage()); } @@ -36,7 +49,8 @@ public class ListenerController { } /** - * 처리 결과 수신 + * 처리 결과(AckDto) 수신 + * TODO 추후 송수신 이력을 관리하는 경우 필요한 로직 추가 */ @PostMapping(value = "/telegram") public AckDto telegram(HttpServletRequest request) { diff --git a/src/main/java/com/bsmlab/dfx/agent/listener/service/ListenerService.java b/src/main/java/com/bsmlab/dfx/agent/listener/service/ListenerService.java index 0f5f873..1b31cdf 100644 --- a/src/main/java/com/bsmlab/dfx/agent/listener/service/ListenerService.java +++ b/src/main/java/com/bsmlab/dfx/agent/listener/service/ListenerService.java @@ -1,21 +1,31 @@ package com.bsmlab.dfx.agent.listener.service; +import com.bsmlab.dfx.agent.config.AgentConfigDto; +import com.bsmlab.dfx.agent.config.AgentConfigReader; import com.bsmlab.dfx.agent.listener.dto.AckDto; import com.bsmlab.dfx.agent.listener.dto.ReceiveMessageDto; import com.bsmlab.dfx.agent.support.MessageUtils; import com.bsmlab.dfx.agent.support.exception.IllegalMessageException; import com.bsmlab.dfx.agent.support.exception.InCompleteMessageException; import com.bsmlab.dfx.agent.support.exception.NullMessageException; +import com.bsmlab.dfx.agent.task.dropbox.DropBoxDto; import com.bsmlab.dfx.agent.task.dropbox.DropBoxService; +import jakarta.servlet.http.Part; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Iterator; + @RequiredArgsConstructor @Slf4j @Service public class ListenerService { private final DropBoxService dropBoxService; + private final AgentConfigReader agentConfigReader; public AckDto receiveMessage(String messageJsonString) { AckDto ackDto = null; @@ -35,4 +45,40 @@ public class ListenerService { } return ackDto; } + + public AckDto receiveFiles(Collection parts) { + AckDto ackDto = null; + try { + if(parts == null || parts.size() < 2) { + throw new IllegalMessageException("파일 전송은 파일의 메타데이터인 application/json 과 n개의 파일 본문인 File Multipart 를 합쳐서 전송하여야 합니다."); + } + else { + Iterator iterator = parts.iterator(); + Part firstPart = iterator.next(); + if(firstPart.getContentType() == null || !firstPart.getContentType().contains("application/json")) { + throw new IllegalMessageException("Multipart의 첫 번째 데이터는 application/json 이어야 합니다."); + } + while(iterator.hasNext()) { + Part filePart = iterator.next(); + if(filePart.getSubmittedFileName() == null) { + throw new IllegalMessageException("Multipart의 두 번째 데이터 및 그 이후 데이터는 File 이어야 합니다."); + } + } + firstPart = iterator.next(); + String messageJsonString = new String(firstPart.getInputStream().readAllBytes(), StandardCharsets.UTF_8); + ReceiveMessageDto receiveMessageDto = MessageUtils.toReceiveMessageDto(messageJsonString); + AgentConfigDto.DropBox dropBox = agentConfigReader.getDropBox(receiveMessageDto.getRecipientDropBoxId()); + String saveDirectoryRoot = dropBox.getSaveDirectoryRoot(); + while(iterator.hasNext()) { + Part part = iterator.next(); + + } + } + } + catch(IllegalMessageException | IOException | InCompleteMessageException | NullMessageException e) { + log.error("{}", e, e); + ackDto = AckDto.builder().result(AckDto.ResultType.RECEIVE_FAIL).resultText(e.getLocalizedMessage()).build(); + } + return ackDto; + } }