티스토리 뷰
iText라는 라이브러리를 사용했다.
필요한 라이브러리 파일은 2개다.
- itextpdf (필자는 5.5.4 버전을 사용) http://sourceforge.net/projects/itext/
- xmlworker (5.5.4 버전 사용) http://sourceforge.net/projects/itextsharp/files/xmlworker/
iText로 HTML->PDF 변환 기능을 구현하면서 가장 애먹었던 작업은 한글과 CSS 문제였다.
한글 변환은 어떻게 해야 한다..라는 참고할 만한 사이트가 별로 없었고(외국 애들은 영어쓰니까 ㅠㅠ), 국내 사이트 중에는 어떤 블로거 분이 http://shonm.tistory.com/450 한글이 되는 소스를 올려주셨는데 문제는 이 소스로 CSS는 어떻게 해야 하는지 모른다는 거였다.
텍스트 자체를 PDF로 변환하는 것은 간단한데, 한글이 온전히 보이면서 CSS까지 먹이려니 여간 짜증나는 작업이 아닐 수 없었다.
(쉬웠던 방법은 StyleSheet로 일일히 속성을 코딩하는 것이었는데, 그짓거리는 하고 싶지 않았다)
한글이 되니까 CSS가 안되고, CSS가 되니까 한글이 안되는 돌아버릴 것 같은 상황의 연속이었지만... 결국엔 해냈다. (self 쓰담쓰담)
베트남 사람한테 도움을 받게 될 줄이야..ㄷㄷ 이 사람도 한자를 PDF로 넣어야 하는데 그 부분에서 막혔던 거다. 영어로 질답해줘서 감사 또 감사...ㅠㅠ
자 그럼,, 아래는 소스다.
3일 동안 개고생해서 정리한 것이니, 감사한 마음으로 가져가 쓰시기를...
Document document = new Document(PageSize.A4, 50, 50, 50, 50); // 용지 및 여백 설정
// PdfWriter 생성
//PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("d:/test.pdf")); // 바로 다운로드.
PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());
writer.setInitialLeading(12.5f);
// 파일 다운로드 설정
response.setContentType("application/pdf");
String fileName = URLEncoder.encode("한글파일명", "UTF-8"); // 파일명이 한글일 땐 인코딩 필요
response.setHeader("Content-Transper-Encoding", "binary");
response.setHeader("Content-Disposition", "inline; filename=" + fileName + ".pdf");
// Document 오픈
document.open();
XMLWorkerHelper helper = XMLWorkerHelper.getInstance();
// CSS
CSSResolver cssResolver = new StyleAttrCSSResolver();
CssFile cssFile = helper.getCSS(new FileInputStream("C:/eGovFrame/workspace/projectName/src/main/webapp/css/pdf.css"));
cssResolver.addCss(cssFile);
// HTML, 폰트 설정
XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
fontProvider.register("C:/eGovFrame/workspace/projectName/src/main/webapp/font/MALGUN.TTF", "MalgunGothic"); // MalgunGothic은 alias,
CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
// Pipelines
PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);
XMLWorker worker = new XMLWorker(css, true);
XMLParser xmlParser = new XMLParser(worker, Charset.forName("UTF-8"));
// 폰트 설정에서 별칭으로 줬던 "MalgunGothic"을 html 안에 폰트로 지정한다.
String htmlStr = "<html><head><body style='font-family: MalgunGothic;'>"
+ "<p>PDF 안에 들어갈 내용입니다.</p>"
+ "<h3>한글, English, 漢字.</h3>"
+ "</body></head></html>";
StringReader strReader = new StringReader(htmlStr);
xmlParser.parse(strReader);
document.close();
writer.close();
↓ pdf.css
p {font-weight: bold;}
h3 {font-size: 15px; font-weight: bold; color: #0082E9; padding:10px 0 10px 0px; margin:0 10px;}
폰트는 한글이 되는 폰트로 특정 경로에 해당 폰트 파일을 넣고, 위 소스에 경로를 설정해주면 된다.
CSS는 디자이너 분 붙잡고 이것저것 다 해본 결과, 클래스나 div는 안먹고 p태그 h태그 같은 아~~주 원초적이고 순수한 것들만 적용됨을 확인할 수 있었다. ㅋㅋㅋ
그 외... API 찾아보면 PDF 문서를 세부적으로 설정해주는 방법들도 있으니 그런 것들은 알아서....
아래는 위 소스의 결과물,,
**** 내용 추가>>> PDF 워터마크, 쪽 번호, 우측 상단 머릿말 넣기.
아래의 클래스를 만든다.
import com.itextpdf.text.Document;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.CMYKColor;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.GrayColor;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;
public class PdfPageEvent extends PdfPageEventHelper {
// Watermark 폰트 설정
// Font FONT = new Font(FontFamily.HELVETICA, 52, Font.BOLD, new GrayColor(0.75f));
Font FONT = new Font(FontFamily.HELVETICA, 52, Font.BOLD, new CMYKColor(64, 11, 0, 0));
Phrase[] header = new Phrase[2];
int pagenumber;
@Override
public void onOpenDocument(PdfWriter writer, Document document) {
header[0] = new Phrase("2015. 01. 07"); // 헤더 머릿말에 넣을 텍스트
}
@Override
public void onChapter(PdfWriter writer, Document document,
float paragraphPosition, Paragraph title) {
header[1] = new Phrase(title.getContent());
pagenumber = 1;
}
@Override
public void onStartPage(PdfWriter writer, Document document) {
pagenumber++;
}
@Override
public void onEndPage(PdfWriter writer, Document document) {
Rectangle rect = writer.getBoxSize("boxName"); // boxName을 PdfWriter.setBoxSize의 boxname 매개 변수와 같게 해야 함.
switch (writer.getPageNumber() % 2) { // 쪽수 쪽, 홀수 쪽 구분해서 속성 적용.
case 0: // 짝수 쪽
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_RIGHT, header[0], rect.getRight(),
rect.getTop(), 0);
break;
case 1: // 홀수 쪽
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_LEFT, header[1], rect.getLeft(),
rect.getTop(), 0);
break;
}
// Watermark
ColumnText.showTextAligned(writer.getDirectContentUnder(),
Element.ALIGN_CENTER, new Phrase("CONFIDENTIAL DOCUMENT", FONT), // 워터마크로 넣을 텍스트
297.5f, 421, writer.getPageNumber() % 2 == 1 ? 45 : -45);
// 쪽 번호 매기기
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_CENTER,
new Phrase(String.format("%d", pagenumber)), // %d의 앞 뒤에 "-" 추가하면 "-1-" 이런 식..
(rect.getLeft() + rect.getRight()) / 2, rect.getBottom() - 18, 0);
}
}
그리고나서, PDF를 변환해주는 코드 부분에 아래 코드를 추가한다.
PdfPageEvent event = new PdfPageEvent(); // Pdf 속성 설정.
writer.setBoxSize("boxName", new Rectangle(36, 54, 559, 788));
writer.setPageEvent(event);
속성 적용해주는 건 여기서 ☞ http://itextpdf.com/examples/iia.php?id=103 참고했음.
'공장 (factory) > - Programming..' 카테고리의 다른 글
Jenkins, Maven 프로젝트 빌드하기 (0) | 2015.06.03 |
---|---|
윈도우에 Jenkins 설치하기 (0) | 2015.06.03 |
[javascript] 팝업창에서 부모창으로 submit. (2) | 2014.12.05 |
[jQuery/javascript] 입력과 동시에 값 유효성 검증 (1) | 2014.11.18 |
[jQuery/javascript] 쿠키(Cookie)를 이용한 ID 저장. (7) | 2014.11.05 |