在日常的办公生活中,尤其是电子档案相关领域,尤其需要注重文书类档案储存的标准化以及处理的标准化以确保电子文档的完整、安全。OFD版式文档格式是电子公文交换和储存格式的国家标准格式。OFD格式在办公中见到的并不是很多的,他是一种归档保存常用的文件格式,可以说是中国版的PDF格式的,办公中我们习惯了使用微软的office办公软件,对于这种格式见得少也是不奇怪的。当然,作为中国版接替PDF的格式,很多方面其实也是和PDF很相似的,比如你想打开这种文档的话,就要使用相关的OFD格式阅读器才行的,你想进行编辑的话,要么下载相应的OFD编辑器,要么先把文档转换成WORD或者是其他格式。
这里用到了“源之缘”前辈的 ofd查看工具:
https://www.cnblogs.com/yuanchenhui/p/ofdreader.html
ofd文件中的文本、图片、样式都需要其中的xml文件配置,OFD.xml和Document.xml比较关键,要说多关键,自己可以去看看。
其实就是往里面加图片,本文就是通过修改xml的方式,往ofd中加图片。
需要使用三个类,一个压缩工具类,一个xml4j工具类,再加一个ofd工具类。其中注意,文件解压再压缩的时候,需要保持目录格式压缩,否则生成ofd文件会打不开,报文件损坏的错误。
package com.zhibei.utils.pfd;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.QName;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import java.io.*;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
public class ZipUtil {
/**
* 缓冲大小
*/
private static int BUFFERSIZE = 2 << 10;
private ZipUtil() {
}
public static void doCompress(String srcFile, String zipFile,String rootdDirectory)
throws IOException {
doCompress(new File(srcFile), new File(zipFile),rootdDirectory);
}
/**
* 文件压缩
*
* @param srcFile
* 目录或者单个文件
* @param zipFile
* 压缩后的ZIP文件
*/
public static void doCompress(File srcFile, File zipFile,String rootdDirectory)
throws IOException {
ZipOutputStream out = null;
try {
out = new ZipOutputStream(new FileOutputStream(zipFile));
doCompress(srcFile, out,rootdDirectory);
} catch (Exception e) {
throw e;
} finally {
out.close();// 记得关闭资源
}
}
public static void doCompress(File file, ZipOutputStream out,String rootdDirectory)
throws IOException {
doCompress(file, out, "",rootdDirectory);
}
public static void doCompress(File inFile, ZipOutputStream out, String dir,String rootdDirectory)
throws IOException {
if (inFile.isDirectory()) {
File[] files = inFile.listFiles();
if (files != null && files.length > 0) {
for (File file : files) {
String name = inFile.getName();
if (!"".equals(dir)) {
name = dir + "/" + name;
}
ZipUtil.doCompress(file, out, name,rootdDirectory);
}
}
}
else {
//将根目录干掉,否则无法打开OFD文件
dir = dir.replaceAll(rootdDirectory+"/", "");
dir = dir.replaceAll(rootdDirectory, "");
ZipUtil.doZip(inFile, out, dir);
}
}
public static void copyFolder(String src,String target) throws IOException {
InputStream in=new FileInputStream(src);
byte[] b=new byte[in.available()];
in.read(b);
OutputStream out=new FileOutputStream(target);
out.write(b);
in.close();
out.close();
}
/***
* 删除文件夹
*
* @param folderPath 文件夹完整绝对路径
*/
public static void delFolder(String folderPath) {
try {
delAllFile(folderPath); // 删除完里面所有内容
String filePath = folderPath;
filePath = filePath.toString();
java.io.File myFilePath = new java.io.File(filePath);
myFilePath.delete(); // 删除空文件夹
} catch (Exception e) {
e.printStackTrace();
}
}
/***
* 删除指定文件夹下所有文件
*
* @param path 文件夹完整绝对路径
* @return
*/
public static boolean delAllFile(String path) {
boolean flag = false;
File file = new File(path);
if (!file.exists()) {
return flag;
}
if (!file.isDirectory()) {
return flag;
}
String[] tempList = file.list();
File temp = null;
for (int i = 0; i < tempList.length; i++) {
if (path.endsWith(File.separator)) {
temp = new File(path + tempList[i]);
} else {
temp = new File(path + File.separator + tempList[i]);
}
if (temp.isFile()) {
temp.delete();
}
if (temp.isDirectory()) {
delAllFile(path + "/" + tempList[i]);// 先删除文件夹里面的文件
delFolder(path + "/" + tempList[i]);// 再删除空文件夹
flag = true;
}
}
return flag;
}
/**
* 解压缩
* @param fileName
* @param path
*/
public static void unzip(String fileName, String path)
{
FileOutputStream fos = null;
InputStream is = null;
try
{
ZipFile zf = new ZipFile(new File(fileName));
Enumeration en = zf.entries();
while (en.hasMoreElements())
{
ZipEntry zn = (ZipEntry) en.nextElement();
if (!zn.isDirectory())
{
is = zf.getInputStream(zn);
File f = new File(path + zn.getName());
File file = f.getParentFile();
file.mkdirs();
fos = new FileOutputStream(path + zn.getName());
int len = 0;
byte bufer[] = new byte[BUFFERSIZE];
while (-1 != (len = is.read(bufer)))
{
fos.write(bufer, 0, len);
}
fos.close();
}
}
}
catch (ZipException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if(null != is)
{
is.close();
}
if(null != fos)
{
fos.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
public static void doZip(File inFile, ZipOutputStream out, String dir)
throws IOException {
String entryName = null;
if (!"".equals(dir)) {
entryName = dir + "/" + inFile.getName();
} else {
entryName = inFile.getName();
}
ZipEntry entry = new ZipEntry(entryName);
out.putNextEntry(entry);
int len = 0;
byte[] buffer = new byte[1024];
FileInputStream fis = new FileInputStream(inFile);
while ((len = fis.read(buffer)) > 0) {
out.write(buffer, 0, len);
out.flush();
}
out.closeEntry();
fis.close();
}
public static void main(String[] args) throws IOException {
XMLWriter writer = new XMLWriter(new FileOutputStream("/1.xml"), OutputFormat.createPrettyPrint());
Document document = DocumentHelper.createDocument();
Element element = document.addElement("Res");
QName s = new QName("Res",null,"ofd:Res");
element.setQName(s);
element.addAttribute("xmlns:ofd","http://www.ofdspec.org/2016");
element.addAttribute("BaseLoc","Res");
writer.write(document);
writer.close();
}
}
package com.zhibei.utils.pfd;
import com.zhibei.utils.WordAPi;
import org.dom4j.*;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import java.io.*;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class XmlUtil {
public static void Xml4ElementValue(String path,String rootname,String attribute,String value) throws IOException {
// 获取XML
Document document = getDocument(path);
Element root = document.getRootElement();
Element paret = root.element("Fonts");
Iterator> ruleNodes = paret.elementIterator(rootname);
while (ruleNodes.hasNext()) {
Element ruleElement = (Element) ruleNodes.next();
// 修改isSelf的属性值
Attribute isSelfAttr = ruleElement.attribute(attribute);
isSelfAttr.setValue(value);
}
writeXml(document, path);
}
public static void Xml4DocumentRes(String path) throws IOException {
// 获取XML
Document document = getDocument(path);
Element root = document.getRootElement();
Element paret = root.element("CommonData");
QName qName = new QName("DocumentRes",null,"ofd:DocumentRes");
Element element = paret.addElement(qName);
element.addText("DocumentRes.xml");
writeXml(document, path);
}
public static void Xml4Res(String path,String workpath) throws IOException {
// 获取XML
Document document = getDocument(path);
Element root = document.getRootElement();
QName qName = new QName("MultiMedias",null,"ofd:MultiMedias");
Element element = root.addElement(qName);
QName qName1 = new QName("MultiMedia",null,"ofd:MultiMedia");
Element element1 = element.addElement(qName1);
element1.addAttribute("ID","1997");
element1.addAttribute("Type","Image");
QName qName2 = new QName("MediaFile",null,"ofd:MediaFile");
Element element2 = element1.addElement(qName2);
element2.addText("zhibei_workmarkph"+workpath.substring(workpath.lastIndexOf(".")));
writeXml(document, path);
}
public static void Xml4ElementText(String path,int status) throws IOException {
// 获取XML
Document document = getDocument(path);
Element root = document.getRootElement();
getNodes(root,status);
writeXml(document, path);
}
public static void getNodes(Element node,int status){
//当前节点所有属性的list
List list = node.attributes();
//递归遍历当前节点所有的子节点
List listElement = node.elements();//所有一级子节点的list
for (Element e : listElement) {//遍历所有一级子节点
if ((null!=e.getText()&&!e.getText().equals(""))){
if (status==1) e.setText(WordAPi.Encrypt(e.getText()));
else e.setText(WordAPi.Decrypt(e.getText()));
}
//添加水印
if (e.getName().equals("Layer")){
Element element = e.addElement("ImageObject");
QName s = new QName("ImageObject",null,"ofd:ImageObject");
element.setQName(s);
element.addAttribute("ID","1997");
element.addAttribute("Boundary","145.5004 233.8589 65.6075 64.0202");
element.addAttribute("CTM","65.61 0.0 0.0 64.02 0.0 0.0");
element.addAttribute("ResourceID","1997");
element.setQName(new QName("ofd:ImageObject"));
}
getNodes(e,status);//递归
}
}
/**
* 得到XML文档
*
* @param xmlFile
* 文件名(路径)
* @return XML文档对象
* @throws DocumentException
*/
public static Document getDocument(String xmlFile) {
SAXReader reader = new SAXReader();
reader.setEncoding("UTF-8");
File file = new File(xmlFile);
try {
if (!file.exists()) {
return null;
} else {
return reader.read(file);
}
} catch (DocumentException e) {
throw new RuntimeException(e + "->指定文件【" + xmlFile + "】读取错误");
}
}
/**
* 得到XML文档(编码格式-gb2312)
*
* @param xmlFile
* 文件名(路径)
* @return XML文档对象
* @throws DocumentException
*/
public static Document getDocument_gb2312(String xmlFile) {
SAXReader reader = new SAXReader();
reader.setEncoding("gb2312");
File file = new File(xmlFile);
try {
if (!file.exists()) {
return null;
} else {
return reader.read(file);
}
} catch (DocumentException e) {
throw new RuntimeException(e + "->指定文件【" + xmlFile + "】读取错误");
}
}
public static String getText(Element element) {
try {
return element.getTextTrim();
} catch (Exception e) {
throw new RuntimeException(e + "->指定【" + element.getName() + "】节点读取错误");
}
}
/**
* 增加xml文件节点
*
* @param document
* xml文档
* @param elementName
* 要增加的元素名称
* @param attrs
* 要增加的元素属性
* @param cdata
* 要增加的元素属性值
*/
public static Document addElementByName(Document document, String elementName, Map attrs, String cdata) {
try {
Element root = document.getRootElement();
Element subElement = root.addElement(elementName);
for (Map.Entry attr : attrs.entrySet()) {
subElement.addAttribute(attr.getKey(), attr.getValue());
}
subElement.addCDATA(cdata);
} catch (Exception e) {
throw new RuntimeException(e + "->指定的【" + elementName + "】节点增加出现错误");
}
return document;
}
/**
* 删除xml文件节点
*/
@SuppressWarnings("unchecked")
public static Document deleteElementByName(Document document, String elementName) {
Element root = document.getRootElement();
Iterator
package com.zhibei.utils.pfd;
import com.zhibei.utils.WordAPi;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.QName;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class Ofdutil {
public static void pfdIo(String path,String workpath,String target,String rootdDirectory,String font,int status,String workmarkph) throws IOException {
ZipUtil.unzip(path, workpath);//unzip src
ZipFile zipFile = new ZipFile(path);
for(Enumeration e = zipFile.entries(); e.hasMoreElements(); ) {
ZipEntry entryIn = (ZipEntry) e.nextElement();
// System.out.println(entryIn.getName());
if(entryIn.getName().contains("PublicRes.xml")){
XmlUtil.Xml4ElementValue(workpath+entryIn.getName(),"Font","FontName",font);
XmlUtil.Xml4ElementValue(workpath+entryIn.getName(),"Font","FamilyName",font);
}
else if (entryIn.getName().contains("Content.xml")){
XmlUtil.Xml4ElementText(workpath+entryIn.getName(),status);
}else if (null!=workmarkph&&!"".equals(workmarkph)&&entryIn.getName().contains("Document.xml")){
File file1 = new File(workpath+"Doc_0/Res");
File file2 = new File(workpath+"Doc_0/DocumentRes.xml");
if (!file1.exists()){
file1.mkdir();
}
//复制水印图片到该路径
System.out.println(file1.exists());
ZipUtil.copyFolder(workmarkph,workpath+"Doc_0/Res"+"/zhibei_workmarkph"+workmarkph.substring(workmarkph.lastIndexOf(".")));
//如果不存在图片配置文件,则创建并添加到Document.xml
if (!file2.exists()){
XMLWriter writer = new XMLWriter(new FileOutputStream(workpath+"Doc_0/DocumentRes.xml"), OutputFormat.createPrettyPrint());
Document document = DocumentHelper.createDocument();
Element element = document.addElement("Res");
QName s = new QName("Res",null,"ofd:Res");
element.setQName(s);
element.addAttribute("xmlns:ofd","http://www.ofdspec.org/2016");
element.addAttribute("BaseLoc","Res");
writer.write(document);
writer.close();
XmlUtil.Xml4DocumentRes(workpath+entryIn.getName());
}
XmlUtil.Xml4Res(workpath+"Doc_0/DocumentRes.xml",workmarkph);
}
}
ZipUtil.doCompress(workpath,target,rootdDirectory);
ZipUtil.delFolder(workpath.substring(0,workpath.length()-1));
}
/**
* @param args
*/
public static void main(String[] args) throws IOException {
// String path ="E:/文档水印.ofd";
// String workpath ="E:/ofdtest/";
// zip(new String[] {"D:/A/feng/feng/src/com/feng/util/ZipUtil.java","D:/A/feng/feng/src/com/feng/test"}, "E:/test/test.zip");
// unzip(path, workpath);
// zip(new String[]{"E:/ofdtest/Doc_0","E:/ofdtest/OFD.xml"},"E:/文档水印1.ofd");
// String rootdDirectory = "ofdtest";
// ZipUtil.doCompress("E:/ofdtest/","E:/文档水印1.ofd",rootdDirectory);
WordAPi.init("E:\\Document\\poi\\Ioc_otl\\src\\main\\resource\\mapper.conf");
System.out.println(WordAPi.Encrypt("智贝"));
System.out.println("**********************************************");
String path ="E:/测试水印.ofd"; //src
String workpath ="E:/ofdtest/"; // work
String target1="E:/测试水印(解密).ofd";
String target2="F:/测试水印(加密).ofd";
String target3="F:/ofdtest.ofd";
String target4="F:/ofdtest加密.ofd";
//
// pfdIo(path,workpath,target1,"ofdtest","宋体",0,"");
pfdIo(target1,workpath,target2,"ofdtest","otl_yahei",1,"F:/印章8.png");
pfdIo(target3,workpath,target4,"ofdtest","otl_yahei",1,"F:/印章8.png");
// pfdIo("D:/1.ofd","D:/ofdtest/","D:/2.ofd","ofdtest","otl_yahei",1);
}
}