替换PDF中的敏感信息
FTP文档中有敏感信息不能显示给客户,之前我采用的是覆盖的方法,但后来发现,那不过是掩耳盗铃,通过覆盖的方法只是在文字表面加了一层遮羞布,一样可以通过搜索和copy获取到我们要加密的内容。
在上一篇博客中,我通过将pdf转为图片之后再转回pdf曲线救国的方式实现了业务需求。
但是今天有一个客户提出新的要求,对方要求pdf不能是图片的方式,因为对方还需要对pdf进行编辑,如果是图片的方式,对方无法进行二次修改。
于是有了这篇文章,
以下这段代码替换了原来的覆盖代码,我们直接将敏感信息替换为空字符。
这一路走来真不容易啊,感叹自己懂的东西还是太少了,一个业务需求愣是让我不断都优化改进,浪费那么多人力物力。我愧对祖国人民,愧对党对我的信任。
/** * 替换敏感词 */
PDDocument doc = null;
try {
doc = PDDocument.load(srcFile);
List pages = doc.getDocumentCatalog().getAllPages();
for (int i = 0; i < pages.size(); i++) {
PDPage page = (PDPage) pages.get(i);
PDStream stream = page.getContents();
PDFStreamParser streamParser = new PDFStreamParser(stream.getStream());
streamParser.parse();
List tokens = streamParser.getTokens();
for (int k = 0; k < tokens.size(); k++) {
Object obj = tokens.get(k);
if (obj instanceof PDFOperator) {
//pdf操作器对象
PDFOperator op = (PDFOperator) obj;
if (Objects.equals(op.getOperation(), "Tj")) {
//COSString对象>>创建java字符串的一个新的文本字符串。
COSString previous = (COSString) tokens.get(k - 1);
//将此字符串的内容作为PDF文本字符串返回。
String val = previous.getString();
for (WordItem item : wordItems) {
if (Objects.equals(item.getContent(), val)) {
Logs.info("内容匹配了");
previous.reset();
//设置字符编码格式
previous.append("".getBytes("GBK"));
}
}
} else if (Objects.equals(op.getOperation(), "TJ")) {
//COSArray是pdfbase对象数组,作为PDF文档的一部分
COSArray previous = (COSArray) tokens.get(k - 1);
//循环previous
for (int j = 0; j < previous.size(); j++) {
//这将从数组中获取一个对象,这将取消引用该对象
//如果对象为cosnull,则返回null
Object arrElement = previous.getObject(j);
if (arrElement instanceof COSString) {
//COSString对象>>创建java字符串的一个新的文本字符串。
COSString cosString = (COSString) arrElement;
//将此字符串的内容作为PDF文本字符串返回。
String val = cosString.getString();
for (WordItem item : wordItems) {
if (Objects.equals(item.getContent(), val)) {
Logs.info("内容匹配了");
cosString.reset();
//设置字符编码格式
cosString.append("".getBytes("GBK"));
}
}
}
}
}
}
}
//创建一个PDStream 流对象
PDStream updatedStream = new PDStream(doc);
//创建一个输出流接收updatedStream
OutputStream out = updatedStream.createOutputStream();
//将接受一个列表并写出它们的流。
ContentStreamWriter tokenWriter = new ContentStreamWriter(out);
//写入一系列标记,后面跟着一行新行
tokenWriter.writeTokens(tokens);
//当前页设置新的内容
page.setContents(updatedStream);
//修改后保存的路径
doc.save(newFile);
}
} catch (Exception e) {
Logs.error(e.getMessage(), e);
}