From 3eeff95da5a06b0f8a29e26f664bcdcf75c4b794 Mon Sep 17 00:00:00 2001 From: Gyumin Sim Date: Sat, 11 May 2024 05:45:51 +0900 Subject: [PATCH] =?UTF-8?q?#9=20feat=20:=20=EC=B1=84=ED=8C=85=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=EA=B8=B0=EB=8A=A5=20=EA=B0=9C=EB=B0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 접속 종료 API - 채팅 파일 업로드 API - 채팅 파일 다운로드 API - 채팅 이미지 업로드 API --- .../controller/chat/ChatController.java | 60 +++++++++++++++++-- .../gdsc/comunity/service/ChatService.java | 39 +++++++++++- 2 files changed, 93 insertions(+), 6 deletions(-) diff --git a/src/main/java/gdsc/comunity/controller/chat/ChatController.java b/src/main/java/gdsc/comunity/controller/chat/ChatController.java index 1cf96cb..5d279e1 100644 --- a/src/main/java/gdsc/comunity/controller/chat/ChatController.java +++ b/src/main/java/gdsc/comunity/controller/chat/ChatController.java @@ -2,16 +2,23 @@ import gdsc.comunity.dto.chat.Chatting; import gdsc.comunity.dto.chat.PagingChatting; +import gdsc.comunity.exception.CustomException; +import gdsc.comunity.exception.ErrorCode; import gdsc.comunity.service.ChatService; +import java.io.File; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import lombok.RequiredArgsConstructor; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.messaging.handler.annotation.DestinationVariable; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.simp.SimpMessageSendingOperations; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; @RestController @RequiredArgsConstructor @@ -19,13 +26,20 @@ public class ChatController { private final SimpMessageSendingOperations messagingTemplate; private final ChatService chatService; - @MessageMapping("/{channelId}/{userNickname}") + @MessageMapping("/{channelId}/{userNickname}/enter") public void enter(@DestinationVariable Long channelId, @DestinationVariable String userNickname){ messagingTemplate.convertAndSend("/api/sub/" + channelId , userNickname); } + @MessageMapping("/{channelId}/{userNickname}/exit") + public void exit(@DestinationVariable Long channelId, + @DestinationVariable String userNickname){ + messagingTemplate.convertAndSend("/api/sub/" + channelId + , userNickname); + } + @MessageMapping("/{channelId}") public void chat(Chatting chatting, @DestinationVariable Long channelId) { chatService.saveChat(chatting, channelId); @@ -33,6 +47,42 @@ public void chat(Chatting chatting, @DestinationVariable Long channelId) { , chatting); } + @PostMapping("/{channelId}/{userNickname}/file") + public void chatFileUpload(@PathVariable Long channelId, @PathVariable String userNickname, @RequestParam("file") MultipartFile file) { + Chatting chatting = chatService.saveChatFile(channelId, userNickname, file); + messagingTemplate.convertAndSend("/api/sub/" + channelId + , chatting); + } + + @PostMapping("/{channelId}/{userNickname}/image") + public void chatImageUpload(@PathVariable Long channelId, @PathVariable String userNickname, @RequestParam("image") MultipartFile[] images) { + Chatting chatting = chatService.saveChatImage(channelId, userNickname, images); + messagingTemplate.convertAndSend("/api/sub/" + channelId + , chatting); + } + + @GetMapping("/file/{fileCode}") + public ResponseEntity chatFileDownload(@PathVariable String fileCode) { + try { + File file = chatService.getChatFile(fileCode); + byte[] fileData = Files.readAllBytes(file.toPath()); + String encodedFileName = URLEncoder.encode(file.getName(), StandardCharsets.UTF_8); + + ByteArrayResource resource = new ByteArrayResource(fileData); + + ResponseEntity responseEntity = ResponseEntity.ok() + .contentType(MediaType.APPLICATION_OCTET_STREAM) + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFileName + "\"") + .body(resource); + + file.delete(); + + return responseEntity; + } catch (Exception e) { + throw new CustomException(ErrorCode.FILE_DOWNLOAD_ERROR); + } + } + @GetMapping("/api/chatLog/{channelId}") public ResponseEntity getChatLog(@PathVariable Long channelId, @RequestParam int page){ diff --git a/src/main/java/gdsc/comunity/service/ChatService.java b/src/main/java/gdsc/comunity/service/ChatService.java index 8e2d701..e45441b 100644 --- a/src/main/java/gdsc/comunity/service/ChatService.java +++ b/src/main/java/gdsc/comunity/service/ChatService.java @@ -3,15 +3,19 @@ import gdsc.comunity.dto.chat.PagingChatting; import gdsc.comunity.dto.chat.Chatting; import gdsc.comunity.entity.chat.ChatLog; +import gdsc.comunity.entity.chat.ChatType; import gdsc.comunity.repository.channel.ChannelRepository; import gdsc.comunity.repository.chat.ChatRepository; import gdsc.comunity.repository.user.UserChannelRepository; +import java.io.File; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; +import java.time.LocalDateTime; import java.util.Map; @Service @@ -21,6 +25,7 @@ public class ChatService { private final ChatRepository chatRepository; private final ChannelRepository channelRepository; private final UserChannelRepository userChannelRepository; + private final S3FileService s3FileService; @Async public void saveChat(Chatting chatting, Long channelId) { @@ -28,7 +33,7 @@ public void saveChat(Chatting chatting, Long channelId) { Long userId = userChannelRepository.getUserIdByNicknameAndChannel(chatting.senderNickname, channelId); - chatRepository.save(chatting.toEntity(channel, userId)); + chatRepository.save(chatting.toEntity(channel, userId, chatting.type)); } public PagingChatting getChatLog(Long channelId, int page) { @@ -38,4 +43,36 @@ public PagingChatting getChatLog(Long channelId, int page) { return PagingChatting.of(chatLogPage, nicknameMap); } + + public Chatting saveChatFile(Long channelId, String userNickname, MultipartFile file) { + String s3filename = s3FileService.uploadFile(file); + + String message = s3filename + "/" + file.getSize(); + + Chatting chatting = new Chatting(message, userNickname, ChatType.FILE, LocalDateTime.now()); + + saveChat(chatting, channelId); + + return chatting; + } + + public Chatting saveChatImage(Long channelId, String userNickname, MultipartFile[] images) { + StringBuilder message = new StringBuilder(); + for (MultipartFile image : images) { + String url = s3FileService.uploadImage(image); + message.append(url).append("/") + .append(image.getOriginalFilename()).append("/") + .append(image.getSize()).append(";"); + } + + Chatting chatting = new Chatting(message.toString(), userNickname, ChatType.IMAGE, LocalDateTime.now()); + + saveChat(chatting, channelId); + + return chatting; + } + + public File getChatFile(String fileCode) { + return s3FileService.downloadFile(fileCode); + } }