diff --git a/src/main/java/com/interplug/qcast/biz/estimate/EstimateService.java b/src/main/java/com/interplug/qcast/biz/estimate/EstimateService.java index 005b6c87..4779b336 100644 --- a/src/main/java/com/interplug/qcast/biz/estimate/EstimateService.java +++ b/src/main/java/com/interplug/qcast/biz/estimate/EstimateService.java @@ -1504,23 +1504,6 @@ public class EstimateService { } while (!prevName.equals(itemName) && itemName.contains("&")); } - // 3. 폰트 미지원 특수문자 치환 - // PDF는 PdfUtil에서 표준 폰트 fallback으로 ® 등을 렌더링하므로 치환 불필요 - // Excel은 MS PGothic 고정이므로 ASCII로 치환 - if (!isPdfDownload) { - itemName = itemName - .replace("\u00AE", "(R)") // ® → (R) - .replace("\u2122", "(TM)") // ™ → (TM) - .replace("\u00A9", "(C)") // © → (C) - .replace("\u2013", "-") // – (en dash) → - - .replace("\u2014", "-") // — (em dash) → - - .replace("\u2018", "'") // ' → ' - .replace("\u2019", "'") // ' → ' - .replace("\u201C", "\"") // " → " - .replace("\u201D", "\"") // " → " - .replace("\u2026", "..."); // … → ... - } - itemResponse.setItemName(itemName); } catch (Exception e) { log.warn("Excel itemName processing failed: {}", itemName); diff --git a/src/main/java/com/interplug/qcast/util/InterfaceQsp.java b/src/main/java/com/interplug/qcast/util/InterfaceQsp.java index f813a461..384b625f 100644 --- a/src/main/java/com/interplug/qcast/util/InterfaceQsp.java +++ b/src/main/java/com/interplug/qcast/util/InterfaceQsp.java @@ -37,41 +37,41 @@ public class InterfaceQsp { * @return String * @throws Exception */ - public String callApi(HttpMethod httpMethod, String apiPath, Object requestObject) - throws Exception { - - URL url = null; - HttpURLConnection con = null; + public String callApi(HttpMethod httpMethod, String apiPath, Object requestObject) + throws Exception { + + URL url = null; + HttpURLConnection con = null; OutputStreamWriter osw = null; - BufferedReader br = null; - StringBuilder sb = null; - long startAt = System.currentTimeMillis(); - String requestType = requestObject == null ? "none" : requestObject.getClass().getSimpleName(); - - try { - - // GET 요청 시 requestObject를 쿼리 스트링으로 변환 - if (HttpMethod.GET.equals(httpMethod) && requestObject != null) { + BufferedReader br = null; + StringBuilder sb = null; + long startAt = System.currentTimeMillis(); + String requestType = requestObject == null ? "none" : requestObject.getClass().getSimpleName(); + + try { + + // GET 요청 시 requestObject를 쿼리 스트링으로 변환 + if (HttpMethod.GET.equals(httpMethod) && requestObject != null) { ObjectMapper om = new ObjectMapper(); Map params = om.convertValue(requestObject, Map.class); // Object -> Map 변환 String queryString = params.entrySet().stream() .map(entry -> entry.getKey() + "=" + entry.getValue()) - .reduce((p1, p2) -> p1 + "&" + p2) - .orElse(""); - apiPath += "?" + queryString; // 쿼리 스트링 추가 - } - - log.debug( - "QSP API call start: method={}, url={}, requestType={}", - httpMethod, - apiPath, - requestType); - url = new URL(apiPath); - con = (HttpURLConnection) url.openConnection(); - con.setConnectTimeout(120000); // 서버에 연결되는 Timeout 시간 설정 - con.setReadTimeout(120000); // InputStream 읽어 오는 Timeout 시간 설정 - con.setRequestMethod(httpMethod.toString()); + .reduce((p1, p2) -> p1 + "&" + p2) + .orElse(""); + apiPath += "?" + queryString; // 쿼리 스트링 추가 + } + + log.debug( + "QSP API call start: method={}, url={}, requestType={}", + httpMethod, + apiPath, + requestType); + url = new URL(apiPath); + con = (HttpURLConnection) url.openConnection(); + con.setConnectTimeout(120000); // 서버에 연결되는 Timeout 시간 설정 + con.setReadTimeout(120000); // InputStream 읽어 오는 Timeout 시간 설정 + con.setRequestMethod(httpMethod.toString()); con.setRequestProperty("Content-Type", "application/json"); con.setRequestProperty("Referer", frontUrl); con.setDoInput(true); @@ -91,33 +91,34 @@ public class InterfaceQsp { } sb = new StringBuilder(); - int status = con.getResponseCode(); - if (status == HttpURLConnection.HTTP_OK) { - br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8")); - - String line; - while ((line = br.readLine()) != null) { - sb.append(line); - } - } - log.debug( - "QSP API call end: method={}, url={}, status={}, durationMs={}", - httpMethod, - apiPath, - status, - System.currentTimeMillis() - startAt); - } catch (Exception e) { - log.error( - "QSP API call failed: method={}, url={}, durationMs={}", - httpMethod, - apiPath, - System.currentTimeMillis() - startAt, - e); - throw e; - } finally { - try { - if (osw != null) osw.close(); - if (br != null) br.close(); + int status = con.getResponseCode(); + if (status == HttpURLConnection.HTTP_OK) { + log.info("[DEBUG] QSP Content-Type: {}", con.getContentType()); + br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8")); + + String line; + while ((line = br.readLine()) != null) { + sb.append(line); + } + } + log.debug( + "QSP API call end: method={}, url={}, status={}, durationMs={}", + httpMethod, + apiPath, + status, + System.currentTimeMillis() - startAt); + } catch (Exception e) { + log.error( + "QSP API call failed: method={}, url={}, durationMs={}", + httpMethod, + apiPath, + System.currentTimeMillis() - startAt, + e); + throw e; + } finally { + try { + if (osw != null) osw.close(); + if (br != null) br.close(); } catch (Exception e) { throw e; } @@ -176,30 +177,30 @@ public class InterfaceQsp { * @return String * @throws Exception */ - public byte[] callApi( - HttpMethod httpMethod, String apiPath, Object requestObject, Map result) - throws Exception { - - URL url = null; + public byte[] callApi( + HttpMethod httpMethod, String apiPath, Object requestObject, Map result) + throws Exception { + + URL url = null; HttpURLConnection con = null; OutputStreamWriter osw = null; - BufferedReader br = null; - - byte[] bt = null; - long startAt = System.currentTimeMillis(); - String requestType = requestObject == null ? "none" : requestObject.getClass().getSimpleName(); - - try { - log.debug( - "QSP API call start: method={}, url={}, requestType={}", - httpMethod, - apiPath, - requestType); - url = new URL(apiPath); - con = (HttpURLConnection) url.openConnection(); - con.setConnectTimeout(30000); // 서버에 연결되는 Timeout 시간 설정 - con.setReadTimeout(30000); // InputStream 읽어 오는 Timeout 시간 설정 - con.setRequestMethod(httpMethod.toString()); + BufferedReader br = null; + + byte[] bt = null; + long startAt = System.currentTimeMillis(); + String requestType = requestObject == null ? "none" : requestObject.getClass().getSimpleName(); + + try { + log.debug( + "QSP API call start: method={}, url={}, requestType={}", + httpMethod, + apiPath, + requestType); + url = new URL(apiPath); + con = (HttpURLConnection) url.openConnection(); + con.setConnectTimeout(30000); // 서버에 연결되는 Timeout 시간 설정 + con.setReadTimeout(30000); // InputStream 읽어 오는 Timeout 시간 설정 + con.setRequestMethod(httpMethod.toString()); con.setRequestProperty("Content-Type", "application/json"); con.setRequestProperty("Referer", frontUrl); con.setDoInput(true); @@ -217,40 +218,40 @@ public class InterfaceQsp { osw.flush(); } } - int status = con.getResponseCode(); - if (status == HttpURLConnection.HTTP_OK) { - // response 헤더 값 결과 셋팅 - result.put("type", con.getHeaderField("Content-Type")); - result.put("disposition", con.getHeaderField("Content-Disposition")); - - InputStream inputStream = con.getInputStream(); + int status = con.getResponseCode(); + if (status == HttpURLConnection.HTTP_OK) { + // response 헤더 값 결과 셋팅 + result.put("type", con.getHeaderField("Content-Type")); + result.put("disposition", con.getHeaderField("Content-Disposition")); + + InputStream inputStream = con.getInputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); - } - bt = outputStream.toByteArray(); // 파일 데이터 반환 - } - log.debug( - "QSP API call end: method={}, url={}, status={}, durationMs={}", - httpMethod, - apiPath, - status, - System.currentTimeMillis() - startAt); - } catch (Exception e) { - log.error( - "QSP API call failed: method={}, url={}, durationMs={}", - httpMethod, - apiPath, - System.currentTimeMillis() - startAt, - e); - throw e; - } finally { - try { - if (osw != null) osw.close(); - if (br != null) br.close(); + } + bt = outputStream.toByteArray(); // 파일 데이터 반환 + } + log.debug( + "QSP API call end: method={}, url={}, status={}, durationMs={}", + httpMethod, + apiPath, + status, + System.currentTimeMillis() - startAt); + } catch (Exception e) { + log.error( + "QSP API call failed: method={}, url={}, durationMs={}", + httpMethod, + apiPath, + System.currentTimeMillis() - startAt, + e); + throw e; + } finally { + try { + if (osw != null) osw.close(); + if (br != null) br.close(); } catch (Exception e) { throw e; } diff --git a/src/main/java/com/interplug/qcast/util/PdfUtil.java b/src/main/java/com/interplug/qcast/util/PdfUtil.java index 3373ff4a..2420dfd0 100644 --- a/src/main/java/com/interplug/qcast/util/PdfUtil.java +++ b/src/main/java/com/interplug/qcast/util/PdfUtil.java @@ -265,7 +265,7 @@ public class PdfUtil { * @return 설정된 FontProvider */ private static DefaultFontProvider setFontProvider(String fontPath) throws IOException { - DefaultFontProvider fontProvider = new DefaultFontProvider(false, true, false); + DefaultFontProvider fontProvider = new DefaultFontProvider(false, false, false); InputStream fontStream = PdfUtil.class.getClassLoader().getResourceAsStream(fontPath); if (fontStream != null) {