From 0bc3eac233240c66057b55c6cbb4e1cae4acf2cf Mon Sep 17 00:00:00 2001 From: Admin Date: Wed, 24 Sep 2025 02:17:01 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EC=B1=84=ED=8C=85=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=A0=84?= =?UTF-8?q?=EC=86=A1=20=ED=8F=AC=EC=8A=A4=ED=8A=B8=EB=A7=A8=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=ED=97=A4=EB=8D=94=20=EB=95=8C=EB=AC=B8=EC=97=90=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EA=B0=80=20=EC=95=88=20=EB=90=A8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 0 -> 6148 bytes src/.DS_Store | Bin 0 -> 6148 bytes src/main/.DS_Store | Bin 0 -> 6148 bytes .../chat/controller/ChatImageController.java | 29 ++++++++++++++++++ .../server/api/chat/dto/ChatImageReqDto.java | 12 ++++++++ .../server/api/chat/dto/ChatImageResDto.java | 13 ++++++++ .../server/api/chat/entity/ChatImage.java | 23 ++++++++++++++ .../chat/repository/ChatImageRepository.java | 7 +++++ .../api/product/service/ChatImageService.java | 22 +++++++++++++ .../server/common/response/SuccessStatus.java | 1 + .../storage/FirebaseStorageService.java | 16 ++++++++++ src/main/resources/.DS_Store | Bin 0 -> 6148 bytes 12 files changed, 123 insertions(+) create mode 100644 .DS_Store create mode 100644 src/.DS_Store create mode 100644 src/main/.DS_Store create mode 100644 src/main/java/com/campick/server/api/chat/controller/ChatImageController.java create mode 100644 src/main/java/com/campick/server/api/chat/dto/ChatImageReqDto.java create mode 100644 src/main/java/com/campick/server/api/chat/dto/ChatImageResDto.java create mode 100644 src/main/java/com/campick/server/api/chat/entity/ChatImage.java create mode 100644 src/main/java/com/campick/server/api/chat/repository/ChatImageRepository.java create mode 100644 src/main/java/com/campick/server/api/product/service/ChatImageService.java create mode 100644 src/main/resources/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..6950f44a04c2460d86245645d35e60b9744fbbd1 GIT binary patch literal 6148 zcmeHKU5nE|6ur}Sx9L`~4~o7B0bk47-O7Ua(yd)kP>`+YgGx=BxQ0zLB}olZ3VBuk zgMYzC|B3&_Cq47An51377ZGN_dS?13M;%X72Xbwz?jl0I5EAEF;?!yzJpVY zar^wZ*v-oIn?+yB%F)Q|i&?bG-pIm57HNeg;wiG4^ni}&5j}zbtg3MBq~hJ8V|X7T z@5jIm44FeQ-z!qllv1b@A;JW#-#?imyAJ=DrsW(+JckWlZkEjT>i*T8he49|df!;B z-q_l1T1~5My&Ave**JC5MKW~a7ozu+^UytOJMOc<&nBI#_j!~$LFC7h5O_XZUOo>Z zk7q-^h`dB{$7;fAS*=Ou`f}OtckTZE-l}Ua@9y`y_MQI0YSpr?-MW46cyb!fBK`q^ z!x*+BY2x)R+DCMB%J0T;6!J(sfHUu+=LKl%w5|39$kn816fg?>nF3;cuu%jKH0BEB z(t%1I0e}q*OG8`y00@q)aiB3*h#44DRG^|VeZ*jjj&WQ24K(Ho6`hzqd@y}yrcWqL z-W}Jsr8}{KLQ@+Bi~?l^>Z;oj`~T7T=l?Rv^o#;Vf&WSY))$39*C%11mu=04fQsAR>*cCZ$7FDJ#4TBX7d% zz@6<@w1p7_=uSF+_W90^KS#C?07RqTssfY%z(ys^6|ne3sGoFBa>imI3L4`$k~cvl z18mcPEWe)t+B*w6;6n)U%>M0T-{zYVwUCKlFi5&)pI?G*6eek<@+xw9YhiK8Ub2h! zm3JoxUh1d)q~Z52sC6o36pZVBa2B=)&C<$&j8i|1+dUN!w%X`&c^<|sIcUg!+)7le zr#tL|U1*lphQoTj?9^-3QP~;p)+%LZyS_6T73|fGt-X`xebkBNqh?;eP2;255; zGFi@p*NY<=-=dBDEl8ma38XW0JY(NSIYwrGKk@JA z%$K8a1b}xiP3Y{hiHv&Dm;f4+gfiw7R}~+`5k+ z68WSS3j%*>WeWy}@QlG1Qgppe63gTUdxy*+gOL?r1z3S8Q^0If*8G&c7rzcGzzY1m z0<=Fk=!CApLZjL`uuv%gB3&buVXUtHhz>O%x&{l4*n%cB6;V@#Nil@U9E7H0ziY-9 z8Z{k+dNR&qo-9m;B23~T95oz-tC34qfE5^3pscG^I{y#9&;LhBTw?`Tfq$ids2q3) zO4AfDKW9cYfL05+D4h4v=!9pXppz%dO$-o6G@T&@Z E0L+bM-T(jq literal 0 HcmV?d00001 diff --git a/src/main/java/com/campick/server/api/chat/controller/ChatImageController.java b/src/main/java/com/campick/server/api/chat/controller/ChatImageController.java new file mode 100644 index 0000000..2931f13 --- /dev/null +++ b/src/main/java/com/campick/server/api/chat/controller/ChatImageController.java @@ -0,0 +1,29 @@ +package com.campick.server.api.chat.controller; + +import com.campick.server.api.chat.dto.ChatImageReqDto; +import com.campick.server.api.chat.dto.ChatImageResDto; +import com.campick.server.api.product.service.ChatImageService; +import com.campick.server.common.response.ApiResponse; +import com.campick.server.common.response.SuccessStatus; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.Map; + +@RestController +@RequestMapping("/api/chat/image") +@RequiredArgsConstructor +public class ChatImageController { + private final ChatImageService chatImageService; + + @PostMapping(consumes = {"multipart/form-data"}) + public ResponseEntity> upload(@RequestPart("chatId") Long chatId, + @RequestPart("file") MultipartFile file) { + String imageUrl = chatImageService.uploadImage(chatId, file); + ChatImageResDto chatImageResDto = ChatImageResDto.builder() + .chatImageUrl(imageUrl).build(); + return ApiResponse.success(SuccessStatus.UPLOAD_CHAT_IMAGE_SUCCESS, chatImageResDto); + } +} diff --git a/src/main/java/com/campick/server/api/chat/dto/ChatImageReqDto.java b/src/main/java/com/campick/server/api/chat/dto/ChatImageReqDto.java new file mode 100644 index 0000000..7dabdcc --- /dev/null +++ b/src/main/java/com/campick/server/api/chat/dto/ChatImageReqDto.java @@ -0,0 +1,12 @@ +package com.campick.server.api.chat.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ChatImageReqDto { + private Long chatId; +} diff --git a/src/main/java/com/campick/server/api/chat/dto/ChatImageResDto.java b/src/main/java/com/campick/server/api/chat/dto/ChatImageResDto.java new file mode 100644 index 0000000..7c90de7 --- /dev/null +++ b/src/main/java/com/campick/server/api/chat/dto/ChatImageResDto.java @@ -0,0 +1,13 @@ +package com.campick.server.api.chat.dto; + +import com.campick.server.api.product.dto.ProductImageResDto; +import lombok.*; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class ChatImageResDto { + private String chatImageUrl; +} \ No newline at end of file diff --git a/src/main/java/com/campick/server/api/chat/entity/ChatImage.java b/src/main/java/com/campick/server/api/chat/entity/ChatImage.java new file mode 100644 index 0000000..429a4f3 --- /dev/null +++ b/src/main/java/com/campick/server/api/chat/entity/ChatImage.java @@ -0,0 +1,23 @@ +package com.campick.server.api.chat.entity; + +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Table(name = "chat_image") +@Getter @Setter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Builder +public class ChatImage { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "chat_id", nullable = false) + private ChatRoom chatRoom; + + @Column(name = "image_url", nullable = false) + private String imageUrl; +} diff --git a/src/main/java/com/campick/server/api/chat/repository/ChatImageRepository.java b/src/main/java/com/campick/server/api/chat/repository/ChatImageRepository.java new file mode 100644 index 0000000..eb3e007 --- /dev/null +++ b/src/main/java/com/campick/server/api/chat/repository/ChatImageRepository.java @@ -0,0 +1,7 @@ +package com.campick.server.api.chat.repository; + +import com.campick.server.api.chat.entity.ChatImage; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ChatImageRepository extends JpaRepository { +} diff --git a/src/main/java/com/campick/server/api/product/service/ChatImageService.java b/src/main/java/com/campick/server/api/product/service/ChatImageService.java new file mode 100644 index 0000000..c6acf46 --- /dev/null +++ b/src/main/java/com/campick/server/api/product/service/ChatImageService.java @@ -0,0 +1,22 @@ +package com.campick.server.api.product.service; + +import com.campick.server.api.chat.repository.ChatImageRepository; +import com.campick.server.common.storage.FirebaseStorageService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.util.Map; + +@Service +@RequiredArgsConstructor +public class ChatImageService { + private final ChatImageRepository chatImageRepository; + private final FirebaseStorageService firebaseStorageService; + + @Transactional + public String uploadImage(Long chatId, MultipartFile file) { + return firebaseStorageService.uploadChatImage(chatId, file); + } +} diff --git a/src/main/java/com/campick/server/common/response/SuccessStatus.java b/src/main/java/com/campick/server/common/response/SuccessStatus.java index 0776859..a0ceacc 100644 --- a/src/main/java/com/campick/server/common/response/SuccessStatus.java +++ b/src/main/java/com/campick/server/common/response/SuccessStatus.java @@ -68,6 +68,7 @@ public enum SuccessStatus { SEND_MY_CHATROOMS(HttpStatus.OK, "내 채팅방 조회 성공"), SEND_TOTAL_UNREAD_MSG(HttpStatus.OK, "총 안 읽은 메시지 수 조회 성공"), COMPLETE_CHAT(HttpStatus.OK, "채팅방 종료 완료"), + UPLOAD_CHAT_IMAGE_SUCCESS(HttpStatus.OK, "채팅방 내 이미지 업로드 성공"), /** diff --git a/src/main/java/com/campick/server/common/storage/FirebaseStorageService.java b/src/main/java/com/campick/server/common/storage/FirebaseStorageService.java index 568a68c..1b2079f 100644 --- a/src/main/java/com/campick/server/common/storage/FirebaseStorageService.java +++ b/src/main/java/com/campick/server/common/storage/FirebaseStorageService.java @@ -84,6 +84,22 @@ public Map uploadProductImage(MultipartFile file) { } } + public String uploadChatImage(Long chatId, MultipartFile file) { + if (file == null || file.isEmpty()) + throw new BadRequestException(ErrorStatus.EMPTY_FILE_EXCEPTION.getMessage()); + + try { + String ext = extractExtension(file.getOriginalFilename()); + String objectName = String.format("chat/%d%s", chatId, ext); + + StorageClient.getInstance().bucket().create(objectName, file.getBytes(), file.getContentType()); + + return String.format("%s/o/%s?alt=media",storageBaseUrl, urlEncode(objectName)); + } catch (IOException e) { + throw new ImageUploadFailedException(ErrorStatus.IMAGE_UPLOAD_FAILED_EXCEPTION); + } + } + private void uploadThumbnail(MultipartFile file, String objectName, int width, int height) throws IOException { ByteArrayOutputStream thumbnailOStream = new ByteArrayOutputStream(); diff --git a/src/main/resources/.DS_Store b/src/main/resources/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..336c5220063af4420a213291e831d44ab58b0e9f GIT binary patch literal 6148 zcmeHKJCD;q5T4D2JBJ7<1+M}mONcHUc_1VN61flxT8y9o6zs&@nRC1*c1RILN(=lC zT1q4;I{pFwg$lmeT|^S!i7OC7(N47c?PF$k=kq?YL?pVCVUwsvL=F;T`82X4g!?%a zq-0vo0EO}q(SUr)DI!_Wwhfj6%fSD}0Po#P*t02qG4}26{hQD=v`Ezw(=PhQsHGGF zd54FTJ&5HXh-CmDe1PmB?fy`L64Ci%{GPG74Aq=??TiEJf(hntm|NQp3onAdRCeZ#2G%(pLG@ z_KvgTRGsJEft-4|pHH%`KYq%!M^eVYud*LJj>2ibcJ`i3az9GKu`-B;Ayl3{iISn5 zcI6})X3Eyn9Ztom^lKMpvv#}gwp-14-JRWPHR|q-_Raac;+(s3{r1EDVLVFYTZ8}+ zIIxxQ0$7%Js1(AA_nY28j?yK?g3d_xdM0$|?w6~dU+sP61#yJl@I-p)!Jo%`RG24*(B^1&jb6v# zLZdb(VICjCj4aFxMX1r?-&N`)IvQHdV$2kdJB!p1ev*xRe`VKi%3e)=W+qqF}To(7Kr^LplGm}W#FGO F@Dnkx*46+3 literal 0 HcmV?d00001 From 42563f2d10d6be1911c2f4e2b86252b04da0f604 Mon Sep 17 00:00:00 2001 From: Admin Date: Wed, 24 Sep 2025 02:17:57 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=EC=B1=84=ED=8C=85=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=A0=84?= =?UTF-8?q?=EC=86=A1=20=ED=8F=AC=EC=8A=A4=ED=8A=B8=EB=A7=A8=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=ED=97=A4=EB=8D=94=20=EB=95=8C=EB=AC=B8=EC=97=90=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EA=B0=80=20=EC=95=88=20=EB=90=A8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index dc2d3b3..4fefe03 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,5 @@ out/ src/main/resources/firebase/ #/src/main/java/com/campick/server/common/config/DataInitializer.java + +*/.DS_Store \ No newline at end of file