Springboot

SpringBoot/한글파일(.hwp) 데이터 바인딩 후 다운로드 하기

25G 2023. 8. 16. 19:17

제가 하는 프로젝트에서 받은 요구사항이 자동으로 문서를 생성하고 다운로드까지 제공해야하는 요구사항이 있었습니다.

  1. 한글 파일에 데이터 바인딩
  2. 문서를 생성(다운로드)

위와같은 절차를 거쳐야 하기 때문에 일반적인 static 파일을 view로 보여주는 요구사항과 비슷해보지만 정말 다른 요구사항을 직면하면서 해결해 나가며 배운 내용입니다.

1. 한글파일 .hml 파일로 확장자 변환하기.

한글파일을 뜯어보면 .hml파일로 확장자를 변환해서 vs 같은 ide 툴로 열어보면 xml 구조로 되어있습니다.
xml 이라는 점을 이용해서 DOM 에 Element 을 이용해서 직접 바인딩을 해주는방법이 있습니다.
(더 좋은방법이 있다면 알려주세요..)

2. 작업하기 쉽게 .hml파일 정렬하기

3. .hml 파일에 바인딩할 태그에 tag달아주기

    <TEXT CharShape="12">
        <CHAR Tag="data">:data</CHAR>
    </TEXT>

4. 해당 dom을 찾아서 데이터 바인딩하기

...

    private final ResourceLoader resourceLoader;


    @GetMapping("/{fileName}")
    public ResponseEntity<String> resouceFileDownload(@PathVariable String fileName) {
        try {
            Resource resource = resourceLoader.getResource("classpath:templates/" + fileName);
            File file = resource.getFile();    //파일이 없는 경우 fileNotFoundException error가 난다.
            DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
            f.setIgnoringElementContentWhitespace(true); // 공백제거
            DocumentBuilder db = f.newDocumentBuilder(); // doc 파일 받는다.
            Document doc = db.parse(file);

            Element root = doc.getDocumentElement();
            NodeList childeren = root.getElementsByTagName("CHAR"); // 태그명
            for (int i = 0; i < childeren.getLength(); i++) {
                Node node = childeren.item(i);
                if(node.getNodeType() == Node.ELEMENT_NODE) { // 해당 노드의 종류 판정(Element일 때)
                    Element ele = (Element)node;
                    if (ele.getAttribute("Tag").equals("data")) {
                        ele.setTextContent("바인딩할 데이터");
                    }
                }
            }
            TransformerFactory transfac = TransformerFactory.newInstance();
            Transformer trans = transfac.newTransformer();

            StringWriter sw = new StringWriter();
            StreamResult result = new StreamResult(sw);
            DOMSource source = new DOMSource(root);
            trans.transform(source, result);
            String xmlString = sw.toString();

            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, file.getName()) // 다운 받아지는 파일 명 설정
                    .header(HttpHeaders.CONTENT_LENGTH, String.valueOf(xmlString.getBytes(StandardCharsets.UTF_8).length))    //파일 사이즈 설정
                    .body(xmlString);    //파일 넘기기
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return ResponseEntity.badRequest()
                    .body(null);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }

element에 바인딩할때 경우에따라선 switch문 이나 여러가지 문법을 이용해서 좀 더 좋은 코드를 작성할 수 있겠습니다.