我們基於FormField 生成pdf 使用了pdfescape 的一個服務,而且默認生成的pdf 文件元數據信息包含了pdfescape的信息,我們可以通過
PdfStamper 對象修改pdf 的一些信息
參考代碼
這個是一個很簡單的demo,實際可以結合業務自己調整
package com.dalong;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
@author dalong
*/
public class Application {
public static void export(){
try {
String fileName = "src/main/resources/授課時間-image.pdf";
String imageFile = "src/main/resources/zeebe.png";
String urlimage = "http://pics7.baidu.com/feed/0d338744ebf81a4c1d4a1627e68e605e242da60b.jpeg?token=3195501e755f94b57a19f8dac7427dad";
PdfReader reader = new PdfReader(fileName);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PdfStamper ps = new PdfStamper(reader, bos);
// 中文字體問題
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
fontList.add(bf);
AcroFields fields = ps.getAcroFields();
fields.setSubstitutionFonts(fontList);
fillData(fields, data());
Map<String,String> info = reader.getInfo();
info.put("Title", "demo web site");
info.put("Subject", "demo ");
info.put("Keywords", "demo ");
info.put("Creator", "dalong");
info.put("Author", "dalong");
info.put("Producer", "dalong");
ps.setMoreInfo(info);
// 添加圖片
addImage(ps,fields,"logo",urlimage);
ps.setFormFlattening(true);
ps.close();
//生成pdf路徑存放的路徑
OutputStream fos = new FileOutputStream("result.pdf");
fos.write(bos.toByteArray());
fos.flush();
fos.close();
bos.close();
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 填充模板中的數據
*/
public static void fillData(AcroFields fields, Map<String, String> data) {
try {
for (String key : data.keySet()) {
String value = data.get(key);
fields.setField(key, value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void addImage(PdfStamper stamper,AcroFields form,String field,String fieldValue){
try{
java.util.List<AcroFields.FieldPosition> photograph = form.getFieldPositions(field);
if(photograph!=null && photograph.size()>0){
Rectangle rect= photograph.get(0).position;
Image img = Image.getInstance(fieldValue);
img.scaleToFit(rect.getWidth(), rect.getHeight());
img.setBorder(2);
img.setAbsolutePosition(
photograph.get(0).position.getLeft() + (rect.getWidth() - img.getScaledWidth() )
, photograph.get(0).position.getTop() - (rect.getHeight()));
PdfContentByte cb = stamper.getOverContent((int)photograph.get(0).page);
cb.addImage(img);
}
}catch(Exception e){
e.printStackTrace();
}
}
/**
* 填充數據源
* 其中data存放的key值與pdf模板中的文本域值相對應
*/
public static Map<String, String> data() {
Map<String, String> data = new HashMap<String, String>();
data.put("year", "2020");
data.put("marks","摘要:這個本來屬於s3 的特性,但是我們在實際使用的過程中肯定不想別人直接可以通過瀏覽器或者http就可以可以我們的文件內容 這個屬於安全的控制,以下是一個實踐以及一些安全控制 一些原則 不能直接暴露minio 訪問到公網環境(可以基於nginx,以及反向代理工具解決) 配置合理的bucket 策略,可以 閱讀全文\n");
data.put("d","因為當前大家主流的還是基於前后端分離的模式開發軟件,組件+api 實現功能,但是很多時候好多租戶對於功能有個性化需求,但是\n" +
"系統在設計的時候因為時間問題+早期設計問題造成業務擴展能力有點差,還需要支持個性化需求開發,所以我們可以拆分標准版本\n" +
"以及自定型版本,同時基於minio 提供的s3 管理模式,對於不同的租戶創建不同的bucket,標准的使用標准版,這樣客戶化開發就很簡單\n" +
"了(特殊場景需要個性化),此方案的缺點也比較明確:空間的占用,但是還好因為前后端分離的模式。每個租戶占用的靜態資源也不是\n" +
"很大,核心問題是在系統更新的時候,我們可能需要引導客戶自己升級或者基於強大的ci/cd 系統進行所有租戶的系統升級(構建包的處理)\n" +
"個人感覺好處也是很明顯的,如果我們的api 以及website 已經做了比較好的版本管理,用戶切換版本也就是靜態資源的替換(直接基於s3 bucket)。\n" +
"saas 應用的功能主要基於單頁面的模式開發的應用,在s3 中的存儲就是css,js 以及靜態html 頁面。這樣管理起來也是比較靈活的");
return data;
}
public static void main(String[] args) {
export();
}
}