20200806更新:此版本好像存在某些bug,复杂的doc替换图片后导致打开时弹出错误修复框。新版见:aspose word 20 java 替换占位符为文字或图片
找了很久Java处理word的方法,poi 处理docx还行,处理doc就总是有各种bug,spire.doc速度有点慢,而且收费,免费版有各种限制。jacob需要依赖服务器安装Microsoft word,而且并发时会有冲突。最终找到一个相对来说好点的aspose word,虽然也要收费,但是有可用的licences就可以直接用了。支持doc和docx。
所需jar包:
链接:https://pan.baidu.com/s/1KERDQ4bb1Mn0tT4S9raPrw
提取码:zc9j
代码:
package aspose;
import com.aspose.words.Document;
import com.aspose.words.DocumentBuilder;
import com.aspose.words.IReplacingCallback;
import com.aspose.words.Node;
import com.aspose.words.ReplaceAction;
import com.aspose.words.ReplacingArgs;
public class ReplaceAndInsertImage implements IReplacingCallback{
public String url;
public ReplaceAndInsertImage(String url){
this.url = url;
}
@Override
public int replacing(ReplacingArgs e) throws Exception {
//获取当前节点
Node node = e.getMatchNode();
//获取当前文档
Document document = (Document) node.getDocument();
DocumentBuilder builder = new DocumentBuilder(document);
// //将光标移动到指定节点
builder.moveTo(node);
// //插入图片
builder.insertImage(url);
return ReplaceAction.REPLACE;
}
}
package aspose;
import java.io.File;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import com.aspose.words.Document;
import com.aspose.words.License;
import com.aspose.words.Range;
public class AsPoseWordUtil {
private static License aposeLic = new License();
private static boolean getlic(){
if(!aposeLic.getIsLicensed()){
InputStream is = AsPoseWordUtil.class.getClassLoader()
.getResourceAsStream("aspose/asposewordLiences.xml");
try {
aposeLic.setLicense(is);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
return true;
}
/**
* aspose word 替换文字/图片。
* @param url 原文件路径
* @param saveurl 保存路径
* @param params {key:value,"$年份$":"2020","$签字1$":"$pic:d/qz1.jpg"} key 为要被替换的字符串,value 为替换为的字符串,替换为图片,则value为$pic:+图片路径
* @return
*/
public static boolean replace(String url,String saveurl,Map<String, String> params){
if(!getlic()){
return false;
}
File file = new File(url);
if(!file.exists()){
return false;
}
try {
Document doc = new Document(url);
Range range = doc.getRange();
for(String key:params.keySet()){
String value = params.get(key);
if(value.startsWith("$pic:")){
value = value.substring(5);
key = key.replace("\\", "\\\\");
key = key.replace("$", "\\$");
key = key.replace("[", "\\[");
key = key.replace("]", "\\]");
key = key.replace("(", "\\(");
key = key.replace(")", "\\)");
key = key.replace("|", "\\|");
key = key.replace("+", "\\+");
key = key.replace("?", "\\?");
key = key.replace("*", "\\*");
range.replace( Pattern.compile(key),new ReplaceAndInsertImage(value) , false);
}else{
range.replace(key, value, true, false);
}
}
doc.save(saveurl);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public static void main(String[] args) {
Map<String, String> params = new HashMap<String, String>();
params.put("[$编号$]", "BH-2020-01-20");
params.put("[$pic$]", "$pic:D:/test/sign.jpg");
AsPoseWordUtil.replace("D:/test/poi替换源.docx", "D:/test/aspose替换后.docx", params);
AsPoseWordUtil.replace("D:/test/poi替换源.doc", "D:/test/aspose替换后.doc", params);
}
}
asposewordLiences.xml:
<License>
<Data>
<Products>
<Product>Aspose.Total for Java</Product>
<Product>Aspose.Words for Java</Product>
</Products>
<EditionType>Enterprise</EditionType>
<SubscriptionExpiry>20991231</SubscriptionExpiry>
<LicenseExpiry>20991231</LicenseExpiry>
<SerialNumber>23dcc79f-44ec-4a23-be3a-03c1632404e9</SerialNumber>
</Data>
<Signature>0nRuwNEddXwLfXB7pw66G71MS93gW8mNzJ7vuh3Sf4VAEOBfpxtHLCotymv1PoeukxYe31K441Ivq0Pkvx1yZZG4O1KCv3Omdbs7uqzUB4xXHlOub4VsTODzDJ5MWHqlRCB1HHcGjlyT2sVGiovLt0Grvqw5+QXBuinoBY0suX0=</Signature>
</License>
效果图:
替换后: