Flask와 Spring Boot를 활용한 비디오 업로드 및 분석 시스템 구현
흐름
- 사용자 업로드 -> 사용자가 브라우저에서 비디오 파일을 업로드
- Spring Boot 처리
-> 업로드된 비디오 파일을 Flask 서버로 전달
-> Flask 서버가 비디오를 분석하고 결과를 반환- 결과 표시
-> Spring Boot가 분석 결과를 HTML로 렌더링하여 사용자에게 같은 페이지에서 결과 표시
해당 페이지의 Spring Boot 디렉터리 구조
com
└── project
└── tailsroute
├── api
│ └── RestTemplateConfig.java // RestTemplate 설정
├── controller
│ └── BehaviorController.java // 요청 처리 컨트롤러
├── service
│ └── BehaviorService.java // Flask 서버와 통신
├── util
│ └── MultipartFileResource.java // 파일 처리 유틸리티
└── templates
└── videoAnalysis.html // 업로드와 결과 HTML
- RestTemplate 설정
- Flask 서버와 HTTP 통신을 위해 RestTemplate을 설정
package com.project.tailsroute.api;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
RestTemplate는 스프링 프레임워크에서 제공하는 클래스로, 다른 프로그램(또는 서버)에 HTTP 요청을 보낼 때 사용된다. 주로, RESTful 웹 서비스와 통신할 때 사용하며, 클라이언트 역할을 한다. 이를 통하여 GET, POST, PUT, DELETE 등의 HTTP 요청을 보냄
- 클라이언트 측에서 다른 서버에 요청을 보내고, 응답을 받을 수 있으며, JSON, XML 같은 데이터를 요청하거나 받을 수 있음
- 요청을 보내고, 응답이 돌아올 때까지 기다리는 동기적인 작업 흐름을 작동
- HTTP 요청을 위한 코드를 단순화하고, 예외 처리를 쉽게 할 수 있도록 도와준다.
package com.project.tailsroute.util;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
public class MultipartFileResource extends ByteArrayResource {
private final String filename;
public MultipartFileResource(MultipartFile file) throws IOException {
super(file.getBytes());
this.filename = file.getOriginalFilename();
}
@Override
public String getFilename() {
return this.filename;
}
}
package com.project.tailsroute.service;
import com.project.tailsroute.util.MultipartFileResource;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
@Service
public class BehaviorService {
private final RestTemplate restTemplate;
public BehaviorService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public String analyzeVideo(MultipartFile file) throws IOException {
String url = "http://localhost:5000/analyze"; // Flask 서버 URL
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file", new MultipartFileResource(file));
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
ResponseEntity<String> response = restTemplate.postForEntity(url, requestEntity, String.class);
if (response.getStatusCode() == HttpStatus.OK) {
return response.getBody();
} else {
throw new RuntimeException("Flask 서버에서 오류 발생: " + response.getStatusCode());
}
}
}
package com.project.tailsroute.controller;
import com.project.tailsroute.service.BehaviorService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
@Controller
@RequestMapping("/usr/behaviorAnalysis")
public class BehaviorController {
private final BehaviorService behaviorService;
public BehaviorController(BehaviorService behaviorService) {
this.behaviorService = behaviorService;
}
@GetMapping("/videoAnalysis")
public String videoAnalysisPage(Model model) {
model.addAttribute("result", null);
return "videoAnalysis";
}
@PostMapping("/videoAnalysis")
public String analyzeVideo(@RequestParam("file") MultipartFile file, Model model) {
try {
String result = behaviorService.analyzeVideo(file);
model.addAttribute("result", result);
} catch (Exception e) {
model.addAttribute("result", "오류 발생: " + e.getMessage());
}
return "videoAnalysis";
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>비디오 분석</title>
</head>
<body>
<h1>비디오 업로드 및 분석</h1>
<form action="/usr/behaviorAnalysis/videoAnalysis" method="post" enctype="multipart/form-data">
<label for="video">비디오 파일 선택:</label>
<input type="file" id="video" name="file" accept="video/*" required>
<br><br>
<button type="submit">업로드 및 분석</button>
</form>
<hr>
<h2>분석 결과</h2>
<div>
<pre>
<p th:text="${result} != null ? result : '분석 결과가 여기에 표시됩니다.'"></p>
</pre>
</div>
</body>
</html>
'팀프로젝트 - TailsRoute' 카테고리의 다른 글
TEAM Project (11.29) - SAMURAI 적용 (0) | 2024.11.30 |
---|---|
TEAM Project (11.28) (0) | 2024.11.28 |
TEAM Project (11.25) - 카카오 소셜 로그인 구현 (0) | 2024.11.25 |
TEAM Project(11.23) - 회원가입 시 이메일 인증 (0) | 2024.11.24 |
TEAM Project - 모델훈련 한계 (0) | 2024.11.23 |