Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

수정사항 적용 #55

Merged
merged 8 commits into from
Jun 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package hello.aimju.chat.chat_room.domain;

import hello.aimju.chat.chat_message.domain.ChatMessage;
import hello.aimju.image.entity.IngredientsImage;
import hello.aimju.user.domain.User;
import hello.aimju.timestamp.Timestamped;
import jakarta.persistence.*;
Expand All @@ -24,6 +25,8 @@ public class ChatRoom extends Timestamped{ // created_at 알아서 생성해줌
private User user;
@OneToMany(mappedBy = "chatRoom", cascade = CascadeType.ALL, orphanRemoval = true)
private List<ChatMessage> chatMessages = new ArrayList<>();
@OneToMany(mappedBy = "chatRoom", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
private List<IngredientsImage> ingredientsImages = new ArrayList<>();

public ChatRoom(User user, String menu) {
this.user = user;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class ChatService {
private final ChatRoomRepository chatRoomRepository;
private final ChatMessageRepository chatMessageRepository;

public void saveChatData(ChatRoomRequestDto chatRoomRequestDto, HttpSession session) {
public Long saveChatData(ChatRoomRequestDto chatRoomRequestDto, HttpSession session) {
// ChatRoom 데이터 저장
ChatRoom chatRoom = new ChatRoom(getUserFromSession(session), chatRoomRequestDto.getMenu());
chatRoomRepository.save(chatRoom);
Expand All @@ -45,6 +45,7 @@ public void saveChatData(ChatRoomRequestDto chatRoomRequestDto, HttpSession sess
chatMessages.add(chatMessage);
}
chatMessageRepository.saveAll(chatMessages);
return chatRoom.getId();
}

public List<GetAllChatRoomResponseDto> getAllChatRooms(HttpSession session) {
Expand Down
15 changes: 8 additions & 7 deletions backend/src/main/java/hello/aimju/controller/ChatController.java
Original file line number Diff line number Diff line change
@@ -1,33 +1,34 @@
package hello.aimju.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import hello.aimju.chat.chat_message.dto.GetAllChatMessageResponseDto;
import hello.aimju.chat.chat_room.dto.ChatRoomRequestDto;
import hello.aimju.chat.chat_room.dto.GetAllChatRoomResponseDto;
import hello.aimju.chat.service.ChatService;
import hello.aimju.image.Service.IngredientsImageService;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;

@RestController
@RequestMapping(value = "/api")
@RequiredArgsConstructor
@CrossOrigin(origins = "http://localhost:3000")
public class ChatController {

private final ChatService chatService;

@Autowired
public ChatController(ChatService chatService) {
this.chatService = chatService;
}

@PostMapping("/recommendation-save")
public ResponseEntity<String> saveChatData(@RequestBody ChatRoomRequestDto chatRoomRequestDto, HttpSession session) {
chatService.saveChatData(chatRoomRequestDto, session);
return ResponseEntity.status(HttpStatus.CREATED).body("Chat data saved successfully.");
Long chatId = chatService.saveChatData(chatRoomRequestDto, session);
return ResponseEntity.status(HttpStatus.CREATED).body(chatId.toString());
}

@GetMapping("/chatrooms")
Expand Down
25 changes: 0 additions & 25 deletions backend/src/main/java/hello/aimju/controller/ImageController.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package hello.aimju.controller;

import hello.aimju.image.Service.IngredientsImageService;
import hello.aimju.image.Service.RoboflowService;
import hello.aimju.image.entity.IngredientsImage;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api")
public class IngredientsImageController {

private final RoboflowService roboflowService;
private final IngredientsImageService ingredientsImageService;

/*
* 사진 업로드 후 재료 인식
* */
@PostMapping("/photo-recognition")
public String uploadImage(@RequestParam("file") MultipartFile file) {
return roboflowService.uploadAndProcessImage(file);
}

/*
* 사진 저장...사용 x
* */
@PostMapping("/photo-save")
public ResponseEntity<String> saveImage(@RequestParam("file") MultipartFile file,
@RequestParam("chatId") String chatId) throws IOException{
if (chatId.isEmpty() || file.isEmpty()) {
return null;
}
Long numberId = Long.parseLong(chatId);
System.out.println("저장 요청 도착: " + numberId);
return ingredientsImageService.saveImage(file, numberId);
}

@GetMapping("/photo/{chatId}")
public ResponseEntity<byte[]> getImageByChatId(@PathVariable("chatId") Long chatId) {
IngredientsImage image = ingredientsImageService.findByChatId(chatId);
if (image == null) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok()
.contentType(MediaType.IMAGE_JPEG) // 적절한 미디어 타입으로 설정
.body(image.getImage());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ private String recipeQuestionBuilder(String menu, String ingredients) {
+ "구체적인 재료와 레시피를 추천해주는데 형식은 반드시 아래와 같아야해 다른말은 하지 말아줘"
+ "\\n메뉴: 음식이름"
+ "재료:\\n1.재료1\\n2.재료2\\n3.재료3\\n"
+ "레시피:\\n1.요리순서1\\n2.요리순서2\\n3.요리순서3";
+ "레시피:\\n1.요리순서1\\n2.요리순서2\\n3.요리순서3\\nn......";
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ public String fetchImageUrl(String query) throws IOException {
System.out.println("Document fetched");

// 이미지 URL 추출
Element imgElement = doc.select("div.common_sp_thumb img").first();
Element imgElement = doc.select("div.common_sp_thumb img:not(.common_vod_label img)").first();

if (imgElement != null) {
String imageUrl = imgElement.attr("src");
System.out.println("Image URL: " + imageUrl);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package hello.aimju.image.Service;

import hello.aimju.chat.chat_room.domain.ChatRoom;
import hello.aimju.chat.chat_room.repository.ChatRoomRepository;
import hello.aimju.image.entity.IngredientsImage;
import hello.aimju.image.repository.IngredientsImageRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

@Service
@RequiredArgsConstructor
public class IngredientsImageService {
private final IngredientsImageRepository ingredientsImageRepository;
private final ChatRoomRepository chatRoomRepository;

public ResponseEntity<String> saveImage(MultipartFile imageFile, Long chatId) throws IOException {
String fileName = imageFile.getOriginalFilename();
byte[] imageData = imageFile.getBytes();

IngredientsImage image = new IngredientsImage();
image.setName(fileName);
image.setImage(imageData);

ChatRoom chatRoom = chatRoomRepository.findById(chatId)
.orElseThrow(() -> new IllegalArgumentException("채팅방을 찾을 수 없습니다. ID: " + chatId));

image.setChatRoom(chatRoom);
ingredientsImageRepository.save(image);

// 성공적인 응답 반환
return ResponseEntity.status(HttpStatus.CREATED).body("채팅이 저장되었습니다.");
}

public IngredientsImage findByChatId(Long chatId) {
ChatRoom chatRoom = chatRoomRepository.findById(chatId)
.orElseThrow(() -> new IllegalArgumentException("채팅방을 찾을 수 없습니다. ID: " + chatId));
return ingredientsImageRepository.findByChatRoom(chatRoom);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import java.util.*;

@Service
public class ImageService {
public class RoboflowService {
// Roboflow API 키
@Value("${roboflow.api-key}")
private String ROBOFLOW_API_KEY;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package hello.aimju.image.entity;

import hello.aimju.chat.chat_room.domain.ChatRoom;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;


@Entity
@Getter
@Setter
public class IngredientsImage {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "name", nullable = false)
private String name;

@Lob
@Column(name = "image", nullable = false, columnDefinition = "LONGBLOB")
private byte[] image;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "chat_Id")
private ChatRoom chatRoom;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package hello.aimju.image.repository;

import hello.aimju.chat.chat_room.domain.ChatRoom;
import hello.aimju.image.entity.IngredientsImage;
import org.springframework.data.jpa.repository.JpaRepository;

public interface IngredientsImageRepository extends JpaRepository<IngredientsImage, Long> {
IngredientsImage findByChatRoom(ChatRoom chatRoom);
}
1 change: 1 addition & 0 deletions frontend/src/app/boards/writing/[recipeId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export default function PostWriting({ params }: { params: { recipeId: number } }
fetchRecipeContent();
} else {
setTitle('제목을 입력해주세요');
fetchRecipes();
setContent('내용을 입력해주세요');
}
}, [params.recipeId]);
Expand Down
36 changes: 30 additions & 6 deletions frontend/src/app/chatroom/[chatroomId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use client'
import React, {useState, useEffect, useCallback} from 'react';
import React, { useState, useEffect, useCallback } from 'react';
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
Expand All @@ -8,6 +8,7 @@ import axios from "axios";
import { useRouter } from "next/navigation";

interface Message {
id: number;
chatType: string;
isUser: number;
content: string;
Expand Down Expand Up @@ -41,6 +42,24 @@ export default function ChatRoom({ params }: { params: { chatroomId: number } })
}
};

// 이미지를 가져오는 함수
const fetchImage = async (chatId: number) => {
try {
// 이미지를 가져오는 API 엔드포인트 호출
const response = await axios.get(`/api/photo/${chatId}`, {
responseType: 'arraybuffer' // 이미지 데이터를 바이너리로 받음
});

// 응답에서 이미지 데이터 추출
const imageData = Buffer.from(response.data, 'binary').toString('base64');

// 이미지를 data URI 형식으로 변환하여 반환
return `data:image/jpeg;base64,${imageData}`;
} catch (error) {
console.error('Error fetching image:', error);
return null;
}
};

useEffect(() => {
axios.get<Message[]>(`/api/chatroom/${params.chatroomId}`)
Expand All @@ -58,7 +77,7 @@ export default function ChatRoom({ params }: { params: { chatroomId: number } })
const recipeString = recipeMessages.map(message => message.content.replace(/<br>/g, "\n")).join("\n");
setRecipeString(recipeString);

const messagesWithLinks = messagesWithBr.map(message => {
const messagesWithComponents = messagesWithBr.map(async (message) => {
if (message.chatType === "link") {
return {
...message,
Expand All @@ -69,20 +88,25 @@ export default function ChatRoom({ params }: { params: { chatroomId: number } })
...message,
content: `<img src="${message.content}" alt="Chat Image" className="rounded-lg" />`
};
} else if (message.chatType === "image") {
// 이미지 가져오기
const imageData = await fetchImage(params.chatroomId);
return {
...message,
content: `<img src="${imageData}" alt="Chat Image" style="max-width: 400px; height: auto;" className="rounded-lg" />`
};
} else {
return message;
}
});
setChatMessages(messagesWithLinks);

Promise.all(messagesWithComponents).then(setChatMessages);
})
.catch(error => {
alert('비정상적인 접근입니다.');
handleRoutingMain();
});
}, [params.chatroomId, handleRoutingMain]);


return (
<>
<Header />
Expand Down Expand Up @@ -120,4 +144,4 @@ export default function ChatRoom({ params }: { params: { chatroomId: number } })
</main>
</>
);
}
}
Loading
Loading