PhantomJS로 GRID&CHART를 PDF 출력하기 (2편 : 페이지설정, Header & Footer )

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


지난번 글 에서 PhantomJS를 이용해서 간단히 Google(우리의 구글신) 화면을 캡쳐했었습니다!

하지만 우리가 단순히 화면만 캡쳐할 거였으면 이미지로 만들었겠죠~

실제로 PhantomJS를 통하여 동일한 로직을 통해 이미지 파일을 추출할 수도 있습니다. (추출파일 확장자만 바꿔주면 되요)


그러나 우린 문서를 원합니다!! 이미지가 아닌 PDF 문서!


문서형식의 파일에는 여러가지 페이지에 대한 설정들이 들어가게 됩니다.

페이지 여백 설정, 방향설정,  페이지 Header, Footer설정, 페이지 크기 등 다양한 설정을 할 수 있어야 하겠지요.


그렇기 때문에 이번에는!

PhantomJS로 그리드&차트 PDF 출력하기 그 두번째 내용으로 PDF 문서의 페이지설정 및 Header와 Footer를 설정해 보도록 하겠습니다.





△실제 웹포넌트 사이트 레포팅 데모를 확인해 보시면 PDF Footer가 나오는 것을 확인하실 수 있습니다.(이미지 클릭!)



일단먼저 실제 웹포넌트 제품이 캡쳐된 이미지를 보실게요. 위 이미지 링크를 타고 가시면 확인하실 수 있는데, 간단하게 페이지의 하단에 페이지 숫자를 표현하고 있습니다. 실제 데모는 저렇듯 간단하디만 페이지 header, footer에는 문서의 제목, 페이지 번호, 이미지 등 다양한 정보를 삽입하실 수 있답니다.


자 그러면 장황한 설명은 이정도 하도록하고 바로 진행해 보도록 하지요!


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
// Web Page를 Control 하기 위한 Web Page Module 객체 생성
var page = require('webpage').create();
 
// PhantomJS에서 화면을 어떤 사이즈로 출력할 것인지에 대한 값
// 미디어 쿼리도 동작
page.viewportSize = { width: 1024, height: 768 };
 
page.onLoadFinished = function(status) {
    console.log('onLoadFinished Status: ' + status);
 
    page.render('screenshot.pdf');    // 스크린 캡쳐파일 생성
      phantom.exit();
}
 
// 페이지 오픈
page.open('http://www.google.com'function(status) {
 
    console.log('open Status: ' + status);
 
    // status 인자를 통해 성공, 실패여부 확인
    if (status !== 'success') {
        console.log('Cannot open webpage');
        phantom.exit();
    } 
});
cs

지난번에 작성했던 코드 전문입니다. 짧지요? ㅋㅋ 


이제 여기에 Header, Footer처리를 붙여보겠습니다.


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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// Web Page를 Control 하기 위한 Web Page Module 객체 생성
var page = require('webpage').create();
 
// PhantomJS에서 화면을 어떤 사이즈로 출력할 것인지에 대한 값
// 미디어 쿼리도 동작
page.viewportSize = { width: 1024, height: 768 };
 
page.paperSize = {
    format: 'A4',
    orientation: 'portrait',
    margin: {
        left: '1cm',
        right: '1cm'
    },
    header: {
        height: '1cm',
        contents: phantom.callback(function () {
            return '<div>PhantomJS Header, Footer 예제입니다.</div>';
        })
    },
    footer: {
        height: '1cm',
        contents: phantom.callback(function (pageNum, numPages) {
            return '<div>' + pageNum + '/' + numPages + '</div>';
        })    
    }
}
 
page.onLoadFinished = function(status) {
    console.log('onLoadFinished Status: ' + status);
 
    page.render('screenshot1.pdf');    // 스크린 캡쳐파일 생성
      phantom.exit();
}
 
// 페이지 오픈
page.open('http://www.google.com'function(status) {
 
    console.log('open Status: ' + status);
 
    // status 인자를 통해 성공, 실패여부 확인
    if (status !== 'success') {
        console.log('Cannot open webpage');
        phantom.exit();
    } 
});
cs


8 ~ 27 line이 추가 되었습니다.

하나하나 설명해 드릴게요.


우선 모든 페이지 설정은 PhantomJS Web Page Module의 pageSize요소를 통해서 가능합니다.

PhantomJS 공식페이지에서는 PDF를 렌더링 할 때 web page의 크기을 정의하는 요소(the size of the web page when rendered as a PDF)라고 설명하고 있네요.


자 이제 처음사용된 요소들 부터 차례대로 설명하겠습니다.


format 우리가 흔히 아는 용지설정 이라고 생각하시면 될 것 같아요. A3, A4, A5, Legal, Letter, Tabloid를 지원한다고 하네요.


orientation은 왜 우리 인쇄할때 가로인쇄 세로인쇄 결정하죠?? 바로 그것입니다. portrait이 세로, landscape가 가로입니다.


margin은 우리가 아는 그 margin이에요. 문서의 여백을 설정할 수 있지요. top, left, bottom, right 다 따로 설정가능하지요.


설정 단위로는 mm, cm, in, px가 있습니다.


또한 위와같은 요소들을 사용하지 않고

{
  width: '200px',
  height: '300px',
  margin: '0px'
}

위와같이 객체안에 width, height을 직접 지정해 줄 수도 있어요. 그러니까 문서의 크기에 관련된 요소들을 다 지정해 줄 수 있겠지요.


자 그럼, 이제 Header, Footer로 넘어가겠습니다!

얘네들은 설명할 부분이 좀 있어요.


코드를 보시죠.

사실 위의 코드는 너무 직관적이라서 설명할 부분이 별로 없어요. 보시면 바로 이해하실 수 있겠죠.

다만 header, footer의 contents 요소는 무조건 phantom.callback object로 설정이 되어야 합니다. 


코드상에서 header는 단순히 문자열을 포함한 div를 return하고 있고, footer는 페이지 번호를 return하는데요, 콜백함수에 pageNum, numPages인자가 넘어와서 페이지 번호를 쉽게 표현할 수 있습니다.


그럼 실제로 pageSize가 적용된 문서와 그렇지 않은 문서를 비교해 볼까요?





왼쪽이 pageSize 적용 안 된 문서, 오른쪽이 적용 된 문서입니다. 차이가 확실하쥬??


일단 문서 모양이 다르죠. 확실히 A4에 맞게 사이즈가 적용된 모습입니다. 또한 양 옆 margin이 설정이 되었고, 위아래 header, footer가 붙었네요.


조금 더 문서처럼 그럴듯하게 보이게 만들어 진 것 같네요.


그렇다면 header나 footer에 스타일을 적용하거나 이미지를 넣을 수는 없을까요?

HTML 태그로 적용되었기 때문에 가능할 것 같습니다. 한번 시도해보죠!




요 webPonent 로고를 Header에 뙇! 그리구 Footer는 색깔을 빨간색으로 바꾼 후 가운데 정렬을 해 보겠습니다.


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


코드를 수정했습니다.

이제 이 스크립트를 실행해 봅시다!

.

.

.

ㅇㅓ??? 왜 안나오지??????


스크린샷을 올리진 않겠습니다. 여러분이 실제로 작성해 보시면서 확인해 보시기 바랍니다.

PDF를 추출해 보시면 footer에는 스타일 적용이 잘 되었는데, header가 휑 하니 비어있을 거에요.

분명히 로고이미지가 있어야 하는데!!!! T^T


이미지를 header나 footer에 삽입하기 위해서는 조금 다른 방법을 사용해야합니다. 

일종의 트릭이지요.

다음 3번째 글에서는 그 방법에 대해 설명해 드리도록 할게요.


긴 글 읽느라 수고하셨고 조만간 세 번째 글로 찾아뵙겠습니다~!


아, 혹여 제가 쓴 정보중에 틀린 부분이나 이해가 안 되시는 부분이 있으면 댓글남겨주세요! 환영합니다!!



New Multi-Channel Dynamic CMS