PhantomJS로 GRID&CHART를 PDF 출력하기 (3편 : Header & Footer에 이미지 넣기)

안녕하세요!! CX사업부 MD 태태입니다!

지난번에 우리가 문서 규격을 갖춘 PDF를 출력하고 헤더, 푸터 까지 출력했었죠.

그런데 기억하시나요?

그 때 우리는 한가지 문제에 직면했었습니다.

기억을 더듬기 위해 지난번 코드의 일부를 살펴보지요.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
page.paperSize = {
    format: 'A4',
    orientation: 'portrait',
    margin: {
        left: '1cm',
        right: '1cm'
    },
    header: {
        height: '1cm',
        contents: phantom.callback(function () {
            var div = document.createElement('div');
            var img  = document.createElement('img');
            img.src = 'http://www.webponent.com/templets/default/img/default/img_logo.gif';
            img.style.height = '0.5cm';
 
            div.appendChild(img);
 
            return div.outerHTML;
        })
    },
    footer: {
        height: '1cm',
        contents: phantom.callback(function (pageNum, numPages) {
            var div = document.createElement('div');
            div.textContent = pageNum + '/' + numPages;
            div.style.color = 'red';
            div.style.textAlign = 'center';
 
            return div.outerHTML;
        })    
    }
}
cs

기억 나시나요??

우린 분명히 header에 이미지경로를 준 <img>태그를 집어넣었어요. webPonent 로고가 나오게 할 생각으로 말이죠. footer에는 페이지 정보에 빨간색으로 스타일을 주었었네요.


그런데 결과는?????

왓????? 나니????

footer는 의도한대로 출력이 되는데 header가 아무것도 나오지가 않지요.

처음에 PDF출력을 구현하면서 이 부분때문에 많이 놀랐었습니다.


자 그러면 이제 어떻게 해결했는지 확인해 봅시다.


해결의 실마리를 얻은 것은 이 github 이슈 였습니다.

간단히 정리해 보면 web상의 resource들이 모두 load되고 loadFinished 이벤트가 발생한 후에는 header,  footer의 HTML들을 파싱하지 않는 phantomJS 버그였던 것이죠.


그래서 생각한 방법은 본문 영역에 display:none 스타일의 이미지를 추가해 캐싱한 후에 그 이미지를 header나 footer에 사용하는 것 이었습니다.


그러면 실제로 테스트를 해보도록 하겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var headerImg = 'http://www.webponent.com/templets/default/img/default/img_logo.gif';
 
page.onLoadFinished = function(status) {
    console.log('onLoadFinished Status: ' + status);
 
 
    // 헤더, 푸터용 이미지 캡쳐 로직
    page.evaluate(function (headerImg) {
        var image = new Image();
        image.src = headerImg;
        image.style.display = 'none';
 
        document.body.appendChild(image);
    }, headerImg);
 
    // 캐싱을 위해 setTimeout 준 후 렌더링
    setTimeout(function () {
        page.render('screenshot.pdf');    // 스크린 캡쳐파일 생성
          phantom.exit();
    }, 500);
}
cs


onLoadFinished lisntner에 body 안에 이미지 태그를 삽입하는 로직을 추가 했습니다.

그리고 안전히 이미지가 캐싱되게 하기위해 setTimeout을 주고 렌더링을 했습니다.

그러면 결과를 확인해 볼까요?


정확하게 헤더에 이미지가 출력되는 것을 확인할 수 있습니다.


이렇게 PDF header, footer에 이미지 출력하는 부분까지 구현해 보았습니다.

웹포넌트 그리드 & 차트 모두 PDF로 출력이 가능한데 지금까지 제가 소개해 드린 phantomJS의 여러가지 렌더링 방법들이 녹아져있답니다.

계속해서 하나씩 소개해 드리도록 하겠습니다 ^^



New Multi-Channel Dynamic CMS