Itext PDF 导出
大约 3 分钟
Itext PDF 导出
给我的文档系统添加了导出,本文记录PDF填坑小结。
PDF导出的实现
导出流
@RequestMapping(value = "export")
public void exportPdfNew(String mdContent, String type, HttpServletResponse response) {
response.reset();
response.setContentType("multipart/form-data");
String title = "file";
String author = "gavin";
String mdFileContent = "";
ServletOutputStream out = null;
try {
byte[] fileBytes = null;
String htmlFile = StringEscapeUtils.unescapeHtml4(mdContent);
String cleanedHtmlFile = htmlFile.replace("<img", "<img style=\"display:inline-block;width:100%;max-width:650px;\" ");
cleanedHtmlFile = cleanHtml(cleanedHtmlFile);
fileBytes = convert(author, cleanedHtmlFile);
response.setHeader("Content-Disposition",
"inline; filename=\"" + title + "_" + System.currentTimeMillis() + ".pdf\"");
out = response.getOutputStream();
out.write(fileBytes);
out.close();
out.flush();
} catch (Exception e) {
System.out.println(e);
}
}
清理HTML
public static String cleanHtml(String input) throws ConversionException, IOException {
InputStream stringAsStream;
try {
stringAsStream = new ByteArrayInputStream(input.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
throw ConversionException.HTML_TO_PDF_EXCEPTION;
}
HtmlCleaner cleaner = new HtmlCleaner();
TagNode node = cleaner.clean(stringAsStream, "UTF-8");
TagNode t = new TagNode("root");
t.addChild(node);
String html = cleaner.getInnerHtml(t);
return html;
}
页眉页脚支持
public class HeaderFooterEvent extends PdfPageEventHelper {
String header, author;
PdfTemplate total;
public void setHeader(String header) {
this.header = header;
}
public void setAuthor(String author) {
this.author = author;
}
public void onOpenDocument(PdfWriter writer, Document document) {
total = writer.getDirectContent().createTemplate(30, 16);
}
// public void onEndPage(PdfWriter writer, Document document) {
// PdfPTable table = new PdfPTable(3);
// try {
// table.setWidths(new int[] { 60, 24, 2 });
// table.setTotalWidth(600);
// table.setLockedWidth(true);
// table.getDefaultCell().setFixedHeight(40);
// table.getDefaultCell().setBorder(Rectangle.BOX);
// table.getDefaultCell().setBorderWidth(0.1f);
// table.getDefaultCell().setBorderColor(Color.gray);
//
// table.addCell(header);
// table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
// table.addCell(String.format("Page %d of", writer.getPageNumber()));
// PdfPCell cell = new PdfPCell(Image.getInstance(total));
// cell.setBorder(Rectangle.BOTTOM);
// table.addCell(cell);
// table.writeSelectedRows(0, -1, 34, 803, writer.getDirectContent());
//
// } catch (DocumentException de) {
// throw new ExceptionConverter(de);
// }
// }
public void onEndPage(PdfWriter writer, Document document) {
PdfContentByte cb = writer.getDirectContent();
cb.saveState();
cb.beginText();
BaseFont bf = null;
try {
bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
} catch (Exception e) {
e.printStackTrace();
}
cb.setColorFill(Color.GRAY);
cb.setFontAndSize(bf, 10);
//Header
float x = document.top(-10);
//左
cb.showTextAligned(PdfContentByte.ALIGN_LEFT,
"Author: " + author,
document.left(), x, 0);
//中
// cb.showTextAligned(PdfContentByte.ALIGN_CENTER,
// writer.getPageNumber()+ " page",
// (document.right() + document.left())/2,
// x, 0);
//右
cb.showTextAligned(PdfContentByte.ALIGN_RIGHT,
"Email: suzhou.daipeng@gmail.com",
document.right(), x, 0);
//Footer
float y = document.bottom(-10);
//左
cb.showTextAligned(PdfContentByte.ALIGN_LEFT,
"Confidential",
document.left(), y, 0);
//中
cb.showTextAligned(PdfContentByte.ALIGN_CENTER,
String.format("- %d -", writer.getPageNumber()),
(document.right() + document.left())/2,
y, 0);
//右
// cb.showTextAligned(PdfContentByte.ALIGN_RIGHT,
// "F-Right",
// document.right(), y, 0);
cb.endText();
cb.restoreState();
}
public void onCloseDocument(PdfWriter writer, Document document) {
ColumnText.showTextAligned(total, Element.ALIGN_LEFT, new Phrase(String.valueOf(writer.getPageNumber() - 1)), 2,
2, 0);
}
}
PDF中文支持
常见的中文支持思路:
- 添加itext-asian.jar
- Windows字体添加到项目中,导出时通过创建该字体对象;
- classpath设置
简单demo如下:
package oliver.itext.demo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
public class PDF2Chinese
{
public static void main(String[] args) throws DocumentException, IOException
{
Document document = new Document();
OutputStream os = new FileOutputStream(new File("chinese.pdf"));
PdfWriter.getInstance(document,os);
document.open();
//方法一: 使用Windows系统字体(TrueType)
BaseFont baseFont = BaseFont.createFont("C:/Windows/Fonts/SIMYOU.TTF",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
//方法二: 使用iTextAsian.jar中的字体
//BaseFont baseFont = BaseFont.createFont("STSong-Light",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
//方法三: 使用资源字体(ClassPath)
////BaseFont baseFont = BaseFont.createFont("/SIMYOU.TTF",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
Font font = new Font(baseFont);
document.add(new Paragraph("解决中文问题了!",font));
document.close();
}
}
通过ITextFontResolvert添加字体
将Windows下fonts中所需要的字体拷贝到项目classpath下:
在代码中通过ITextFontResolver
添加字体,具体代码如下:
public byte[] convert(String author, String input)
throws ConversionException, IOException, com.lowagie.text.DocumentException {
ITextRenderer renderer = new ITextRenderer();
renderer.setDocumentFromString(new String(input.getBytes()));
renderer.setPDFVersion(PdfWriter.VERSION_1_7);
HeaderFooterEvent headerFooterEvent = new HeaderFooterEvent();
headerFooterEvent.setAuthor(author);
renderer.setPdfPageEvent(headerFooterEvent);
ITextFontResolver fontResolver = renderer.getFontResolver();
fontResolver.addFont(fontPath+"MSYH.TTC", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);// 微软雅黑
fontResolver.addFont(fontPath+"MSYHBD.TTC", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
fontResolver.addFont(fontPath+"MSYHL.TTC", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
renderer.layout();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
renderer.createPDF(outputStream);
byte[] bytes = outputStream.toByteArray();
return bytes;
}
PDF Linux环境下中文字体乱码
用itext生成pdf在windows环境下没有出现中文乱码而在linux下出现中文乱码,打开pdf查看pdf编码,以及显示的编码,发现编码并没有对应。原因是使用的宋体和微软雅黑在linux环境下并没有安装。
解决方法
- 由于我这边PDF生成是通过HTML转化的,所以第一步先导出HTML,去查看需要用哪些字体文件;
- 到windows环境下将所需字体拷贝到linux下。(simsun.ttc(宋体), msyf.ttf(微软雅黑))
- 到linux环境下创建目录
mkdir -pv /usr/share/fonts/chinese/TrueType
将字体放入目录下
cd /usr/share/fonts/chinese/TrueType
chmod 755 * 为字体赋予可执行权限
- 建立字体缓存
mkfontscale (如果提示 mkfontscale: command not found,需自行安装 # yum install mkfontscale )
mkfontdir
fc-cache -fv (如果提示 fc-cache: command not found,则需要安装# yum install fontconfig )
- reboot重启系统
经不同Linux环境测试,以上步骤必须顺序全部执行, 建立字体缓存必须是在字体拷贝完成之后顺序执行 mkfontscale,mkfontdir,fc-cache -fv