티스토리 뷰

   iText라는 라이브러리를 사용했다.


   필요한 라이브러리 파일은 2개다.

- itextpdf (필자는 5.5.4 버전을 사용) http://sourceforge.net/projects/itext/

- xmlworker (5.5.4 버전 사용) http://sourceforge.net/projects/itextsharp/files/xmlworker/



itext-5.5.6.zip


xmlworker-5.5.6.zip


   iText로 HTML->PDF 변환 기능을 구현하면서 가장 애먹었던 작업은 한글과 CSS 문제였다.


   한글 변환은 어떻게 해야 한다..라는 참고할 만한 사이트가 별로 없었고(외국 애들은 영어쓰니까 ㅠㅠ), 국내 사이트 중에는 어떤 블로거 분이 http://shonm.tistory.com/450 한글이 되는 소스를 올려주셨는데 문제는 이 소스로 CSS는 어떻게 해야 하는지 모른다는 거였다.


   텍스트 자체를 PDF로 변환하는 것은 간단한데, 한글이 온전히 보이면서 CSS까지 먹이려니 여간 짜증나는 작업이 아닐 수 없었다.

   (쉬웠던 방법은 StyleSheet로 일일히 속성을 코딩하는 것이었는데, 그짓거리는 하고 싶지 않았다)


   한글이 되니까 CSS가 안되고, CSS가 되니까 한글이 안되는 돌아버릴 것 같은 상황의 연속이었지만... 결국엔 해냈다. (self 쓰담쓰담)


   iText의 API도 뒤져보고 다른 사람들이 올려놓은 소스들도 죄다 살펴보면서 하나하나 조각을 끼워맞췄다.

   결정적으로 도움이 됐던 사이트는 http://www.wenda.io/questions/4902142/how-to-export-vietnamese-text-to-pdf-using-itext.html 여기였다.

   베트남 사람한테 도움을 받게 될 줄이야..ㄷㄷ 이 사람도 한자를 PDF로 넣어야 하는데 그 부분에서 막혔던 거다. 영어로 질답해줘서 감사 또 감사...ㅠㅠ



   자 그럼,, 아래는 소스다.

   3일 동안 개고생해서 정리한 것이니, 감사한 마음으로 가져가 쓰시기를...


// Document 생성
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 참고했음.



댓글
  • 감사한 마음으로 사용하겠습니다^^ 2015.02.26 17:37 신고
  • 저우니 완전 감사해요!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2015.03.30 21:20 신고
  • fehead 와 이틀동안 고생한것을 이곳에서 한방에 처리했네요.
    감사합니다 ㅡ.ㅜ

    참고로 spring view 렌더링 결과를 출력할려면

    // viewResolver servlet-*.xml 에 있는 viewResolver
    @Autowired ViewResolver viewResolver;

    ....

    // 비지니스 로직
    model.addAttribute("test", 1);
    model.addAttribute("test", 1);
    //

    LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
    View view = viewResolver.resolveViewName("front/viewprint", localeResolver.resolveLocale(request));
    // front/viewprint --> /WEB-INF/view/front/viewprint.jsp 파일 지정

    MockHttpServletResponse mockResp = new MockHttpServletResponse();
    view.render(model.asMap(), request, mockResp);
    String renderedHtml = mockResp.getContentAsString(); // 렌더링한 결과값 가져오기.

    renderedHtml --> 이것을 pdf로 렌더링 하면됩니다. 주의 img 파일이나 css 파일을 full url로 변경 필요
    2015.04.15 19:59 신고
  • BlogIcon 공부하는 나부랭이, 무중력고기 호의를 호구로 아는 몇몇 사람들 때문에 솔직히 요즘 정보 공유하기 싫었는데, 님 같은 분들이 있어서 힘이 납니다. 추가 정보 감사합니다. 2015.04.16 18:24 신고
  • 쪽박 가뭄에 단비같은 내용이네요...
    정말 감사합니다.
    2015.04.17 16:05 신고
  • 아귀 자바 초보입니다.
    먼저 dll파일을 어떻게 추가하나요?

    그리고 6번째쭐 PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream()); 에서
    response가 없다고 뜨네요;;
    2015.05.26 12:10 신고
  • BlogIcon 공부하는 나부랭이, 무중력고기 maven이나 gradle을 써와서, 아귀님 댓글보고 간만에 제가 올린 파일을 확인했네요. 라이브러리 파일 직접 추가하실 거라면, 구글 검색하시면 금방 찾으실 수 있을 겁니다. 그리고 response는 HttpResponse 객체가 있다는 전제 하에 사용한 변수명이고요. 2015.06.01 10:40 신고
  • BlogIcon 공부하는 나부랭이, 무중력고기 첨부파일 다시 찾아서 넣어놨고요. 위에 링크 걸어놓은 사이트 들어가서도 받을 수 있습니다. 2015.08.05 14:13 신고
  • 지나가는행인 한글 뜨는거 보고 울뻔했습니다.
    덕분에 퇴근합니다.
    감사합니다.
    2015.06.11 21:48 신고
  • 우앙 html이랑 여기있는내용으로 css먹여서 pdf파일 만드는거 성공했어요!
    한글뜨니 정말감동 ㅠㅠ 한참 헤매었는데 진심으로 감사드립니다.
    그런데 질문하나만 드릴께요.
    제가 javascript에 jquery를 이용해서 pdf파일 생성시 적용하고 싶은데 며칠동안 여기저기
    소스를 다뒤져도 완성을 못해서요 ㅠㅠ
    데이터 가져와서 html에 뿌려주고 html에 있는 첫번째 table높이를 측정해서 일정길이가 넘어가면
    div를 다음장으로 넘겨주려고 하는데요.
    javascript를 적용하는 방법이있는거 같은데 제가 개발에 많이 서툴러서요....
    도움이 될만한 소스나 참고할만한 사이트좀 정중히 부탁드립니다.
    2015.10.15 18:22 신고
  • BlogIcon 공부하는 나부랭이, 무중력고기 잘 돌아간다니 다행입니다.
    근데 안타깝게도 제가 요즘 iText를 만지고 있지 않아서요.
    구글링 한번 열심히 해보심이 좋을 듯합니다.ㅎㅎ
    2015.10.16 15:04 신고
  • BlogIcon 우앙 아고 그래도 다른질문처럼 div id를 불러오지 못한다는건 알아서 다행입니다. 감사합니다. 2015.10.23 14:11 신고
  • 자바초보 정말 잘 배우고 가요 ㅜㅜㅜ
    포기할 뻔 했는데 겨우 배웠어요!
    혹시 질문이 있는데요~
    div id로는 pdf로 내보내지 못하나요?ㅠㅠ 감사합니당!
    2015.10.20 22:36 신고
  • BlogIcon 공부하는 나부랭이, 무중력고기 iText 라이브러리 만든 사람들한테 여쭤보세요 ㅋㅋ
    제가 해본 바로는 div는 안됐습니다.
    2015.10.21 14:15 신고
  • 자바초보 답변해주셔서 감사해요!
    잘 배우고 갑니다. 굽신굽신!
    2015.10.21 16:24 신고
  • 감사합니다. 많은 도움 되었습니다. 2015.11.02 16:24 신고
  • 감사합니다 div까지는 먹는듯하네요. 클래스는 안먹는듯 ㅜㅜ 2015.11.11 20:12 신고
  • geeny 우연히 검색하다 보게되었는데 덕분에 쉽게 해결하게 되겠네요.
    저도 글쓴분같이 나중에 경력쌓아서 좋은글 많이 남기고 싶네요.
    감사합니다.
    2016.03.15 09:36 신고
  • BlogIcon 공부하는 나부랭이, 무중력고기 저 경력은 짧습니다 ㅎㅎ
    좋은 개발자 되시기를!
    2016.03.18 09:52 신고
  • 뫄뫄잉뿌 감사해요!! 정만 도움이 많이 됬습니다 ㅠㅠ 2016.04.29 09:16 신고
  • 린스 감사합니다. 도움이 되었습니다. 2016.05.16 15:34 신고
  • zzz 감사합니다! 도움이 많이 됩니다^^ 2016.08.02 09:28 신고
  • 개발자0001 좋은글 감사합니다.
    근데 제가 itext를 사용할때 이상하게 margin과 float등 몇가지 css 효과들이 먹히지 않는 거 같은데
    뭐 따로 설정하신 거 있으신가요..??
    2016.09.30 20:01 신고
  • BlogIcon 공부하는 나부랭이, 무중력고기 따로 설정한 것은 없습니다. 2016.10.06 13:11 신고
  • 초급개발 정말감사합니다. 많은 도움이 되었습니다 2016.10.06 10:31 신고
  • 마리링 안녕하세요. 정말 도움이 많이 되었습니다! 정말정말 감사합니다.
    위에 댓글에서도 있는 내용인데... css 효과들이 몇몇 먹히지 않아서 저도 너무 고생했었는데요... (저는 table에 border-top이나 border-left 이런것들이 안되었죠 ㅠㅠ) 해당 부분에 th나 td를 더 추가해서 <td style="background:#D5D5D5; width:1px;"></td> 이런식으로 선을 그렸습니다..ㅠㅠ 어떻게든 하면 안되는것은 없네요 ㅎㅎㅎ 다시한번 정말 감사합니다!
    2016.10.19 16:29 신고
  • 고도리 잘 배우고 갑니다^^
    근데 <table border='1'> 이거 먹이면 항상 표에 굵은 선이 나와요;; 얇은 선으로 하고 싶은데.. 이것때문에 몇일째 고생중인데 뭔가 방법이 없을까요ㅠㅠ
    2016.12.29 11:09 신고
  • BlogIcon 공부하는 나부랭이, 무중력고기 http://www.webmadang.net/script/script.do?action=read&boardid=3003&page=1&seq=36

    구글링 검색하면 5초도 안돼서 찾을 수 있는데 이걸로 며칠째 고생하셨다니 대단하네요.

    여긴 왕초보 분들 a부터 z까지 알려주는 학원아닙니다. 알아서들 찾으세요.
    2016.12.30 20:55 신고
  • 행인 좋은 자료 감사드립니다. 2017.04.20 15:22 신고
  • 행인2 정말 감사합니다. 많은 도움이 되었습니다 ㅜㅠ! 2018.04.09 18:18 신고
댓글쓰기 폼
Total
1,009,812
Today
155
Yesterday
258
«   2018/05   »
    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    
글 보관함