docx转PDF,耗时异常

版本:23.8
编程语言:java

有个文件转换耗时很长,麻烦帮看下是什么原因呢,这是耗时监控:

源文件:
0202-续签劳动合同&保密协议&脱密期协议-无固定期限-上传版.docx (146.8 KB)

转换代码:

public void convertToPdf(InputStream in, OutputStream out,List<WordParams> params,int saveFormat) throws Exception { 
		logger.info("使用新版本aspose"); 
		Document doc = createDocument(in); 
		if(params != null && params.size() > 0) { 
			for(WordParams wordParams :  params) { 
				FindReplaceOptions options = new FindReplaceOptions(); 
				Color color = getColor(wordParams.getColor()); 
				if(color != null) { 
					options.getApplyFont().setColor(color); 
				} 
				if (BooleanUtils.isTrue(wordParams.getHighlight())) { 
					options.getApplyFont().setHighlightColor(Color.YELLOW); 
				} 
				doc.getRange().replace(wordParams.getName(), wordParams.getValue(), options); 
			} 
		} 
 
		FontSettings fontSettings = FontSettings.getDefaultInstance(); 
		FolderFontSource folderFontSource = new FolderFontSource(FONTS_FOLDER, false, 1); 
		SystemFontSource systemFontSource = new SystemFontSource(2); 
		fontSettings.setFontsSources(new FontSourceBase[] { systemFontSource, folderFontSource }); 
		doc.setFontSettings(fontSettings); 
		doc.getLayoutOptions().setCommentDisplayMode(CommentDisplayMode.HIDE); 
		doc.acceptAllRevisions(); 
 
		if (saveFormat == SaveFormat.PDF){ 
			PdfSaveOptions opts = new PdfSaveOptions(); 
			opts.setUpdateFields(false); 
			opts.setSaveFormat(saveFormat); 
			doc.save(out, opts); 
		} else { 
			doc.save(out, saveFormat); 
		} 
 
	}```

@ZhonghaoSun 在我这边,转换本身大约需要 7 秒。这是一个可以接受的转换时间。但是,我认为你的代码还有改进的空间。

  1. 你在每次文档处理操作中都配置了默认的 FontSettings。这会导致 Aspose.Words 每次都扫描你的字体源。如果你的字体源中有很多字体,那么这个操作可能会花费相当长的时间。

你可以在应用程序启动时配置一次默认的 FontSettings。这将缩短文档处理时间。

  1. 在你的代码中,你遍历了 List<WordParams>,并对每个项执行单独的查找/替换操作。你可以将所有键合并到一个正则表达式中,然后在一次查找/替换操作中全部替换它们,从而达到同样的效果。请看以下修改后的代码:

这部分代码应该移到类的静态构造函数中,或者在应用程序启动事件中执行:

FontSettings fontSettings = FontSettings.getDefaultInstance();
FolderFontSource folderFontSource = new FolderFontSource(FONTS_FOLDER, false, 1);
SystemFontSource systemFontSource = new SystemFontSource(2);
fontSettings.setFontsSources(new FontSourceBase[] { systemFontSource, folderFontSource });

修改后的 convertToPdf 方法:

public static void convertToPdf(InputStream in, OutputStream out,List<WordParams> params,int saveFormat) throws Exception {
    Document doc = new Document(in);
    if(params != null && params.size() > 0) {
        FindReplaceOptions options = new FindReplaceOptions();
        options.setReplacingCallback(new MyFindReplaceCallback(params));
        getColor(wordParams.getColor());
        if (color != null) {
            options.getApplyFont().setColor(color);
        }
        if (BooleanUtils.isTrue(wordParams.getHighlight())) {
            options.getApplyFont().setHighlightColor(Color.YELLOW);
        }
        doc.getRange().replace(getPattern(params), "", options);
    }

    doc.getLayoutOptions().setCommentDisplayMode(CommentDisplayMode.HIDE);
    doc.acceptAllRevisions();
        
    if (saveFormat == SaveFormat.PDF){
        PdfSaveOptions opts = new PdfSaveOptions();
        opts.setUpdateFields(false);
        opts.setSaveFormat(saveFormat);
        doc.save(out, opts);
    } else {
        doc.save(out, saveFormat);
    }
}
private static Pattern getPattern(List<WordParams> params)
{
    String regexPattern = params.stream()
            .map(WordParams::getName)
            .map(Pattern::quote) // Escapes special regex characters
            .collect(Collectors.joining("|")); // Joins with an OR separator

    return Pattern.compile(regexPattern);
}
private static class MyFindReplaceCallback implements IReplacingCallback
{
    public MyFindReplaceCallback(List<WordParams> params)
    {
        mParams = params;
    }
        
    @Override
    public int replacing(ReplacingArgs replacingArgs) throws Exception {
            
        // Get the matched text.
        String matchValue = replacingArgs.getMatch().group();
        // Get the replacement value.
        WordParams value = mParams.stream()
                .filter(p -> matchValue.equals(p.getName()))
                .findAny()
                .orElse(null);
        // There is nothing to replace.
        if(value==null)
            return ReplaceAction.SKIP;
            
        replacingArgs.setReplacement(value.getValue());
        return ReplaceAction.REPLACE;
    }
        
    private  List<WordParams> mParams;
}