<aside> 🍀 영수증 OCR API 명세서 → 명세서를 확인하며 API를 개발했습니다.

</aside>

Client 측 OCR 호출 함수

const submit = async () => {
        const formData = new FormData();
        const file = base64toFile(image, 'image_file.png');
        formData.append("uploadFile", file);
        await axios.post("<https://nengcipe-server.store/api/clovaOCR>", formData, {
            headers: {
                Authorization: "Bearer eyJhbGciOiJIUzI1NiJ9.eyJtZW1iZXJJZCI6InRlc3QxMjMiLCJpZCI6MSwiaWF0IjoxNjg0Mjk4NTA3LCJleHAiOjE2ODQyOTkxMDd9.2lX3kEOL_mxHkL-ZJQYGfPjzPmUz3bcIVvw84WeJF6c"
            }
        }).then(data =>
            console.log(data.data.images));
    }

영수증 사진.png

Untitled

OCRController

@RestController
public class OCRController {
    @Autowired
    private OCRService ocrService;
    @PostMapping("/api/clovaOCR")
    public ResponseEntity<Object> clovaOCR(@RequestPart("uploadFile") MultipartFile file){
        String tempDir = System.getProperty("java.io.tmpdir");
        System.out.println("임시 디렉토리 경로: " + tempDir);
        Object result = null;

        try {
            result=ocrService.clovaOCRService(multipartFileToFile(file));
        } catch (Exception e) {
            e.printStackTrace();
        }
        ResultResponse res = ResultResponse.builder()
                .code(HttpStatus.OK.value())
                .message("영수증 정보 가져오기 성공.")
                .result(result).build();
        return new ResponseEntity<>(res, HttpStatus.OK);
    }

		//Client가 제공하는 MultipartFile을 File 형식으로 변경해야함 (NaverOcr Docs기반)
    public File multipartFileToFile(MultipartFile file) throws IOException {
        InputStream inputStream = file.getInputStream();
        File convertedFile = File.createTempFile("temp", null);
        FileOutputStream fileOutputStream = new FileOutputStream(convertedFile);
        IOUtils.copy(inputStream, fileOutputStream);
        fileOutputStream.close();
        inputStream.close();
        return convertedFile;
    }
}

OCRService

@Service
public class OCRService {

    @Value("${ocr.url}")
    private String apiURL;
    @Value("${ocr.secretKey}")
    private String secretKey;

    public Object clovaOCRService(File file) { 

        List<List<String>> result;

        try {
            URL url = new URL(apiURL);
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            con.setUseCaches(false);
            con.setDoInput(true);
            con.setDoOutput(true);
            con.setReadTimeout(30000);
            con.setRequestMethod("POST");
            String boundary = "----" + UUID.randomUUID().toString().replaceAll("-", "");
            con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
            con.setRequestProperty("X-OCR-SECRET", secretKey);
            JSONObject json = new JSONObject();
            json.put("version", "V2");
            json.put("requestId", UUID.randomUUID().toString());
            json.put("timestamp", System.currentTimeMillis());
            JSONObject image = new JSONObject();
            image.put("format", "jpg");
            image.put("name", "demo");
            JSONArray images = new JSONArray();
            images.put(image);
            json.put("images", images);
            String postParams = json.toString();

            con.connect();
            DataOutputStream wr = new DataOutputStream(con.getOutputStream());
            long start = System.currentTimeMillis();
            writeMultiPart(wr, postParams, file, boundary);
            wr.close();

            int responseCode = con.getResponseCode();
            BufferedReader br;
            if (responseCode == 200) {
                br = new BufferedReader(new InputStreamReader(con.getInputStream()));
            } else {
                br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
            }
            String inputLine;
            StringBuffer response = new StringBuffer();
            while ((inputLine = br.readLine()) != null) {
                response.append(inputLine);
            }
            br.close();

            System.out.println(response); // API 호출 결과를 콘솔에 출력
            // jsonToString() 메소드 호출하고 결과 받아옴
            result = jsonToString(response.toString());
            System.out.println(result);
            return result;

        } catch (Exception e) {
            System.out.println("서비스에러");
            System.out.println(e);

        }
        return null;
    }

    private static void writeMultiPart(OutputStream out, String jsonMessage, File file, String boundary) throws
            IOException {
        StringBuilder sb = new StringBuilder();
        sb.append("--").append(boundary).append("\\r\\n");
        sb.append("Content-Disposition:form-data; name=\\"message\\"\\r\\n\\r\\n");
        sb.append(jsonMessage);
        sb.append("\\r\\n");

        out.write(sb.toString().getBytes("UTF-8"));
        out.flush();

        if (file != null && file.isFile()) {
            out.write(("--" + boundary + "\\r\\n").getBytes("UTF-8"));
            StringBuilder fileString = new StringBuilder();
            fileString
                    .append("Content-Disposition:form-data; name=\\"file\\"; filename=");
            fileString.append("\\"" + file.getName() + "\\"\\r\\n");
            fileString.append("Content-Type: application/octet-stream\\r\\n\\r\\n");
            out.write(fileString.toString().getBytes("UTF-8"));
            out.flush();

            try (FileInputStream fis = new FileInputStream(file)) {
                byte[] buffer = new byte[8192];
                int count;
                while ((count = fis.read(buffer)) != -1) {
                    out.write(buffer, 0, count);
                }
                out.write("\\r\\n".getBytes());
            }

            out.write(("--" + boundary + "--\\r\\n").getBytes("UTF-8"));
        }
        out.flush();
    }

    public List<List<String>> jsonToString(String jsonResultStr) throws JSONException {
        String result = "";

        List<List<String>> mainResult = new ArrayList<>();

        JSONObject jsonObj = new JSONObject(jsonResultStr);

        JSONArray imageArray = jsonObj.getJSONArray("images");

        JSONObject tempObj = imageArray.getJSONObject(0);
        JSONObject receiptObj = tempObj.getJSONObject("receipt");

        JSONObject resultObj = receiptObj.getJSONObject("result");
        JSONArray subResultArray = resultObj.getJSONArray("subResults");
        JSONObject temp2Obj = subResultArray.getJSONObject(0);
        JSONArray itemsArray = temp2Obj.getJSONArray("items");

        for (int i = 0; i < itemsArray.length(); i++) {
            JSONObject sparseObj = (JSONObject) itemsArray.get(i);
            String nameResultStr = sparseObj.getJSONObject("name").getString("text");
            String countResultStr = sparseObj.getJSONObject("count").getString("text");
            List<String> subResult = new ArrayList<>();
            subResult.add(nameResultStr);
            subResult.add(countResultStr);
            mainResult.add(subResult);
        }

        System.out.println(mainResult);
        //[[생삼겹살, 25], [맥주, 4], [음료수, 4], [밥+된장, 13]]

        return mainResult;
    }
}