先导入jar包
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.8</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
import cn.dazc.mediatecenter.utils.StrTool;
import cn.donganzichan.casefeign.feign.ICaseBatchFeign;
import cn.donganzichan.common.bean.web.ResponseResult;
import com.alibaba.fastjson.JSONObject;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.http.entity.ContentType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Component;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.io.IOException;
/**
* @author hyy
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class PdfService {
private final ICaseBatchFeign caseBatchFeign;
@SneakyThrows
public String contentToPdf(String content,String name) {
// 创建一个文档
Document document = new Document(PageSize.A4, 10, 10, 10, 10);
String path = System.getProperty("user.dir") + "//" + name + ".pdf";
try(OutputStream outputStream = new FileOutputStream(path)) {
PdfWriter pdfWriter = PdfWriter.getInstance(document, outputStream);
// 添加页眉页脚
pdfWriter.setPageEvent(new PdfBuilder(new String[]{"", ""}));
document.open();
XMLWorkerHelper.getInstance().parseXHtml(pdfWriter, document,
new ByteArrayInputStream(("<html><body>"+content+"</body></html>").getBytes(StandardCharsets.UTF_8)),
StandardCharsets.UTF_8,new AsianFontProvider());
} catch (Exception e) {
log.error("生成pdf异常",e);
return null;
} finally {
document.close();
}
// 将生成的pdf到oss
try {
File file = new File(path);
InputStream is = new FileInputStream(file);
ResponseResult<JSONObject> oss = caseBatchFeign.uploadOSS(new MockMultipartFile(file.getName(), file.getName(),
ContentType.APPLICATION_OCTET_STREAM.toString(), is));
// 存完OSS,服务器不留存
FileUtils.forceDelete(new File(path));
String url = oss.getData().getString("path");
if (StrTool.isEmpty(url))
log.error("上传pdf失败");
return url;
} catch (Exception e) {
log.error("上传pdf失败",e);
// 存完OSS,服务器不留存
FileUtils.forceDelete(new File(path));
return null;
}
}
static class AsianFontProvider extends XMLWorkerFontProvider {
@Override
public Font getFont(final String fontname, String encoding, float size, final int style) {
String fntname = fontname;
if (fntname == null) {
// 本地下载的字体文件,resources目录下
fntname = "simsun.ttf";
}
if (size == 0) {
size = 4;
}
return super.getFont(fntname, encoding, size, style);
}
}
static class PdfBuilder extends PdfPageEventHelper {
/**
* 页眉
*/
public String header = "";
/**
* 文档字体大小,页脚页眉最好和文本大小一致
*/
public int presentFontSize = 12;
/**
* 文档页面大小,最好前面传入,否则默认为A4纸张
*/
public Rectangle pageSize = PageSize.A4;
// 模板
public PdfTemplate total;
public BaseFont bf = null;
/**
* 利用基础字体生成的字体对象,一般用于生成中文文字
*/
public Font fontDetail = null;
///-------------------------------我是分界线---------------------------------------//
/**
* leftHeader
*/
private final Phrase leftHeader;
private final Phrase rightHeader;
private static BaseFont baseFont;
/**
* 生成下划线空白占位符
*/
private static String Blank;
/**
* 页眉字体
*/
public static Font font;
/**
* 下划线字体
*/
private static Phrase blankPhrase;
public PdfBuilder(String[] header) {
this.leftHeader = new Phrase(header[0], PdfBuilder.font);
this.rightHeader = new Phrase(header[1], PdfBuilder.font);
}
static {
try {
// 中文字体依赖itext得itext-asian包
baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 211; i++) {
sb.append("\u00a0");
}
Blank = sb.toString();
font = new Font(PdfBuilder.baseFont, 12, Font.UNDEFINED);
blankPhrase = new Phrase(PdfBuilder.Blank, new Font(PdfBuilder.baseFont, Font.DEFAULTSIZE, Font.UNDERLINE));
} catch (DocumentException | IOException e) {
e.printStackTrace();
}
}
/**
* 档打开时创建模板
*/
@Override
public void onOpenDocument(PdfWriter writer, Document document) {
// 共 页 的矩形的长宽高
total = writer.getDirectContent().createTemplate(50, 50);
}
@Override
public void onEndPage(PdfWriter writer, Document document) {
int yMargin = -20;
float top = document.top(yMargin);
float bottom = document.bottom(-65);
try {
if (bf == null) {
bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
}
if (fontDetail == null) {
// 数据体字体
fontDetail = new Font(bf, presentFontSize, Font.NORMAL);
}
} catch (DocumentException | IOException e) {
e.printStackTrace();
}
//生成下划线,使用空格占位
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_LEFT, PdfBuilder.blankPhrase,
document.right(-25), top, 180);
//底部下划线
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_LEFT, PdfBuilder.blankPhrase,
document.right(-25), bottom, 180);
//生成左侧页眉
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_LEFT, leftHeader,
document.left(), 38, 0);
//生成右侧页眉
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_RIGHT, rightHeader,
document.right(), 0, 0);
//生成页脚页数
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_RIGHT, new Phrase("注:对本模板如有疑问,请及时与java开发组联系 ", new Font(PdfBuilder.baseFont, 8, Font.UNDEFINED)), document.right(), document.bottom(-45), 0);
// 1.写入页眉
ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_LEFT, new Phrase(header, fontDetail), document.left(), document.top() + 20, 0);
// 2.写入前半部分的 第 X页/共
int pageS = writer.getPageNumber();
String foot1 = "第 " + pageS + " 页 /共";
Phrase footer = new Phrase(foot1, fontDetail);
// 3.计算前半部分的foot1的长度,后面好定位最后一部分的'Y页'这俩字的x轴坐标,字体长度也要计算进去 = len
float len = baseFont.getWidthPoint(foot1, presentFontSize);
// 4.拿到当前的PdfContentByte
PdfContentByte cb = writer.getDirectContent();
// 5.写入页脚 X=215 Y= -80
ColumnText.showTextAligned(cb, Element.ALIGN_CENTER, footer, (document.rightMargin()
+ document.right() + document.leftMargin() - document.left() - len) / 2.0F + 215F, document.bottom() - 80, 0);
// 6.写入页脚2的模板
cb.addTemplate(total, (document.rightMargin() + document.right() + document.leftMargin()
// 调节模版显示的位置
- document.left()) / 2.0F + 215F, document.bottom() - 80);
}
/**
* 关闭文档时,替换模板,完成整个页眉页脚组件
*/
@Override
public void onCloseDocument(PdfWriter writer, Document document) {
// 关闭文档的时候,将模板替换成实际的 Y 值
total.beginText();
// 生成的模版的字体、颜色
total.setFontAndSize(baseFont, presentFontSize);
String foot2 = " " + (writer.getPageNumber()) + " 页";
//模版显示的内容
total.showText(foot2);
total.endText();
total.closePath();
}
}
}