import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.io.FileInputStream;
import org.apache.commons.io.IOUtils;
@Slf4j
@RestController
public class OcrController {
private static final ObjectMapper objectMapper = new ObjectMapper();
private static final String ROOT_DIR = ".."; // 프로젝트 Root 경로
private static final String OCR_RESULT_DIR = ROOT_DIR + "/tmp/work"; // OCR 처리된 이미지를 저장할 위치
private static final String OCR_API_URL = ""; // OCR API URL
private static final String OCR_API_KEY = ""; // OCR API Key
/**
* OCR API를 호출합니다.
* @param file
* @param page
* @return
*/
@PostMapping("/requestOCR")
public ResultModel ocrRequest(
@RequestParam("file") MultipartFile file,
@RequestParam(value = "page", required = false, defaultValue = "0") int page) {
ResultModel model = new ResultModel();
model.setResult("false");
try {
OCRResult ocrResult = getOcrResult(file, page);
String fileName = downloadImage(ocrResult.getMasked_image());
String imagePath = String.format("%s/viewImage?fileName=%s", ServletUriComponentsBuilder.fromCurrentContextPath().toUriString(), fileName);
model.setResult(ocrResult);
model.setImagePath(imagePath);
return model;
} catch (IOException e) {
log.warn(e.getMessage(), e);
return model;
}
}
/**
* 이미지 바이트 배열을 가져옵니다.
* @param fileName
* @return
* @throws IOException
*/
@GetMapping("/viewImage")
public ResponseEntity<byte[]> getImageByteArray(String fileName) throws IOException {
InputStream imageStream = new FileInputStream(String.format("%s/%s", OCR_RESULT_DIR, fileName));
byte[] imageByteArray = IOUtils.toByteArray(imageStream);
imageStream.close();
return new ResponseEntity<>(imageByteArray, HttpStatus.OK);
}
/**
* OCR result를 반환합니다.
* @param file
* @param page
* @return
* @throws IOException
*/
private OCRResult getOcrResult(MultipartFile file, int page) throws IOException {
OCRResult ocrResult = requestOCR(file, page);
if (ocrResult == null) {
throw new IOException("OCR request failed.");
}
return ocrResult;
}
/**
* OCR API를 호출합니다.
* @param file
* @param page
* @return
* @throws IOException
*/
private OCRResult requestOCR(MultipartFile file, int page) throws IOException {
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
File f = new File("/C:/image/" + file.getOriginalFilename());
file.transferTo(f);
FileSystemResource fileSystemResource = new FileSystemResource(f);
body.add("api_key", OCR_API_KEY);
body.add("page_index", String.valueOf(page));
body.add("image", fileSystemResource);
body.add("type", "upload");
body.add("coord", "origin");
body.add("skew", "image");
body.add("boxes_type", "all");
body.add("save_mask", true);
body.add("textout", true);
body.add("recog_form", true);
body.add("extract_table", true);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
String serverUrl = OCR_API_URL + "/ocr";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.postForEntity(serverUrl, requestEntity, String.class);
return this.objectMapper.readValue(this.objectMapper.readTree(response.getBody()).get("result").toString(), OCRResult.class);
}
/**
* OCR 결과이미지를 다운로드 합니다.
* @param fileName
* @return
* @throws IOException
*/
private String downloadImage(String fileName) throws IOException {
URL url = new URL(OCR_API_URL + "/out/" + fileName);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
String formData = "api_key=" + OCR_API_KEY;
connection.setDoOutput(true);
try (OutputStream outputStream = connection.getOutputStream()) {
byte[] formDataBytes = formData.getBytes("UTF-8");
outputStream.write(formDataBytes, 0, formDataBytes.length);
}
int statusCode = connection.getResponseCode();
String statusMessage = connection.getResponseMessage();
if (statusCode == 200) {
System.out.println("OCR image download 성공");
String outFilePath = String.format("%s/%s", OCR_RESULT_DIR, fileName);
try (InputStream inputStream = connection.getInputStream();
FileOutputStream outputStream = new FileOutputStream(outFilePath)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}
return fileName;
} else {
System.out.println("OCR image download 실패: " + statusCode);
throw new IOException(statusMessage);
}
}
} |