Word转pdf后,复选框未勾选

word转pdf后,word中已勾选的复选框,在转换PDF后未勾选

word:
image.png (29.0 KB)

PDF:
image.png (13.0 KB)

@guzhuo 请在此分享原始文件和代码,以供测试。

文件:
测试.docx (68.9 KB)

/*
 * Ant Group
 * Copyright (c) 2004-2023 All Rights Reserved.
 */
package com.alipay.alriskassesscore.service.word.impl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import com.alibaba.common.logging.Logger;
import com.alibaba.common.logging.LoggerFactory;

import com.alipay.alriskassesscore.base.code.ErrorCode;
import com.alipay.alriskassesscore.base.exception.RaRpcException;
import com.alipay.alriskassesscore.service.word.WordService;
import com.alipay.alriskassesscore.util.log.RaLoggerUtil;
import com.alipay.antlaw.util.LoggerUtil;
import com.aspose.words.Document;
import com.aspose.words.FontSettings;
import com.aspose.words.SaveFormat;
import com.aspose.words.StreamFontSource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

/**
 * 提供word文档处理
 *
 * @author zt01638014
 * @version WordServiceImpl.java, v 0.1 2023年06月27日 上午11:24 zt01638014
 */
@Service
public class WordServiceImpl implements WordService, InitializingBean {

    /**
     * logger
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(WordServiceImpl.class);


    private StreamFontSource[] fontSourceBases;

    /**
     * afterPropertiesSet
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        initAsposeLic();
    }

    /**
     * 加载转pddf配置
     * @throws Exception aspose加载异常
     */
    private void initAsposeLic() throws Exception {
        LOGGER.warn("begin init aspose");
        com.aspose.words.License wlicense = new com.aspose.words.License();
        ClassPathResource classPathResource = new ClassPathResource("word/Aspose.Total.Java.lic");
        InputStream is = classPathResource.getInputStream();
        wlicense.setLicense(is);
        //初始化aspose执行引擎
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        Document doc = new Document(new ByteArrayInputStream("init".getBytes()));
        doc.updatePageLayout();
        doc.save(baos, SaveFormat.DOCX);
        LOGGER.warn("init aspose success !!");
        //加载字体
        List<StreamFontSource> sourceList = new ArrayList<>();
        sourceList.add(loadFontResource("Alibaba-PuHuiTi-Bold.otf"));
        sourceList.add(loadFontResource("Alibaba-PuHuiTi-Heavy.otf"));
        sourceList.add(loadFontResource("Alibaba-PuHuiTi- Light.otf"));
        sourceList.add(loadFontResource("Alibaba-PuHuiTi-Medium.otf"));
        sourceList.add(loadFontResource("Alibaba-PuHuiTi-Regular.otf"));
        sourceList.add(loadFontResource("Alibaba-PuHuiTi-Regular.ttf"));
        sourceList.add(loadFontResource("AlibabaSans-Black.otf"));
        sourceList.add(loadFontResource("AlibabaSans-Bold.otf"));
        sourceList.add(loadFontResource("AlibabaSans-BoldItalic.otf"));
        sourceList.add(loadFontResource("AlibabaSans-Heavy.otf"));
        sourceList.add(loadFontResource("AlibabaSans-HeavyItalic.otf"));
        sourceList.add(loadFontResource("AlibabaSans-Italic.otf"));
        sourceList.add(loadFontResource("AlibabaSans-Light.otf"));
        sourceList.add(loadFontResource("AlibabaSans-LightItalic.otf"));
        sourceList.add(loadFontResource("AlibabaSans-Medium.otf"));
        sourceList.add(loadFontResource("AlibabaSans-MediumItalic.otf"));
        sourceList.add(loadFontResource("AlibabaSans-Regular.otf"));
        sourceList.add(loadFontResource("Arial.ttf"));
        sourceList.add(loadFontResource("Arial Bold.ttf"));
        sourceList.add(loadFontResource("Arial Bold Italic.ttf"));
        sourceList.add(loadFontResource("Arial Italic.ttf"));
        sourceList.add(loadFontResource("CALIBRI.TTF"));
        sourceList.add(loadFontResource("CALIBRIB.TTF"));
        sourceList.add(loadFontResource("CALIBRII.TTF"));
        sourceList.add(loadFontResource("CALIBRIL.TTF"));
        sourceList.add(loadFontResource("CALIBRILI.TTF"));
        sourceList.add(loadFontResource("CALIBRIZ.TTF"));
        sourceList.add(loadFontResource("DFHeiGB-W3.otf"));
        sourceList.add(loadFontResource("SimSun.ttf"));
        sourceList.add(loadFontResource("Songti.ttc"));
        sourceList.add(loadFontResource("STHeiti Light.ttc"));
        sourceList.add(loadFontResource("Times New Roman.ttf"));
        sourceList.add(loadFontResource("Times New Roman Bold.ttf"));
        sourceList.add(loadFontResource("Times New Roman Bold Italic.ttf"));
        sourceList.add(loadFontResource("Times New Roman Italic.ttf"));
        fontSourceBases = sourceList.toArray(new StreamFontSource[0]);
    }

    /**
     * 加载字体
     * @param name 字体库名称
     * @return aspose字体
     */
    private StreamFontSource loadFontResource(String name){
        LoggerUtil.debug(LOGGER, "减少代码重复率");
        StreamFontSource streamFontSource = new StreamFontSource() {
            @Override
            public InputStream openFontDataStream() throws Exception {
                LoggerUtil.debug(LOGGER, "减少代码重复率");
                ClassPathResource fontDirResource = new ClassPathResource("font/"+name);
                LoggerUtil.debug(LOGGER, "减少代码重复率");
                return fontDirResource.getInputStream();
            }
        };
        LoggerUtil.debug(LOGGER, "减少代码重复率");
        return streamFontSource;
    }

    /**
     * 将word文件转换成pdf文件
     * @param word  word文件流
     * @return 转换为pdf文件流
     */
    @Override
    public InputStream convertWord2Pdf(InputStream word) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            Document doc = new Document(word);
            doc.setFontSettings(new FontSettings());
            doc.getFontSettings().setFontsSources(fontSourceBases);
            doc.save(baos,SaveFormat.PDF);
            return new ByteArrayInputStream(baos.toByteArray());
        } catch (Exception e) {
            RaLoggerUtil.error(e, LOGGER, "[fail]convertWord2Pdf");
            throw new RaRpcException(ErrorCode.code("SERVICE_RPC_EXCEPTION", e));
        } finally {
            try {
                if (word != null) {
                    word.close();
                }
            } catch (IOException var3) {
                RaLoggerUtil.error( LOGGER, "wordService closeQuietly excepion......", var3);
                throw new RaRpcException(ErrorCode.code("SERVICE_RPC_EXCEPTION", var3));
            }
        }
    }
}

@guzhuo 你这边好像漏掉了一些字体。对于复选框通常负责Wingdings字体。请检查是否有字体替换的警告 (链接)。

...
HandleDocumentWarnings handleDocumentWarnings = new HandleDocumentWarnings();
doc.setWarningCallback(handleDocumentWarnings);
...

public static class HandleDocumentWarnings implements IWarningCallback {    
    public void warning(WarningInfo info) {
        if (info.getWarningType() == WarningType.FONT_SUBSTITUTION) {
            System.out.println("Font substitution: " + info.getDescription());
            FontWarnings.warning(info);
        }
    }

    public WarningInfoCollection FontWarnings = new WarningInfoCollection();
}

此外,您还可以通过以下方式检查文档使用的字体:

FontInfoCollection allFonts = doc.getFontInfos();

我添加了 Wingdings字体后,转换仍然不正确。

wingdings.zip (108.5 KB)

sourceList.add(loadFontResource("Wingdings.ttf"));
        sourceList.add(loadFontResource("Wingdings 2.ttf"));
        sourceList.add(loadFontResource("Wingdings 3.ttf"));

@guzhuo WarningCallback 内部是否有任何警告?

只有这两个

2024-03-06 12:10:20,797 [0600aac4170969821219971492246269 0.15 - /// - ] WARN  impl.WordServiceImpl - Aspose.save, WarningType:[FONT_SUBSTITUTION], Description:Font 'MS Gothic' has not been found. Using 'Alibaba PuHuiTi B' font instead. Reason: font info substitution.
2024-03-06 12:10:20,841 [0600aac4170969821219971492246269 0.15 - /// - ] WARN  impl.WordServiceImpl - Aspose.save, WarningType:[MINOR_FORMATTING_LOSS], Description:Table column widths may need to be calculated. Rendered column widths could differ.```

@guzhuo 请尝试添加 "MS Gothic "并告知结果。

这个字体暂时没找到,可以在哪里下载吗?

@guzhuo 尝试使用此
msgothic.zip (4.5 MB)

感谢,验证异常已经恢复了,文件名需要改成【MS Gothic.ttc】。

另外这种遗漏字体的情况有办法规避吗?提前添加所有的字体?

@guzhuo 遗憾的是,目前还没有专门的方法来避免遗漏字体的问题。你所能做的就是设置字体或包含字体的文件夹,或为某些字体配置可替代的字体。不过,通常基本的 Windows 字体足以解决大多数问题。