Word 文档转换 PDF、图片

工作有需要 Word 文档转换 PDF、图片 的场景,我们来看看 Java 开发中怎么解决这个问题的。

Word 转 PDF

Word 转 PDF 分为商用 Aspose 方案和开源 Apache POI+iText 方案。

Aspose 方案

这种方式在目前来看应该是最好的,无论是转换的速度还是成功的概率,还支持的文件类型。

由于 Aspose 并非开源软件,不会在 Maven 公开依赖,故我们要手动加入到 Maven 管理中去。


<dependency>
    <groupId>com.asposegroupId>
    <artifactId>aspose-wordsartifactId>
    <version>15.8version>
    <scope>systemscope>
    <systemPath>${project.basedir}/jar/aspose-words-15.8.0-jdk16.jarsystemPath>
dependency>

添加依赖

因为是手动添加的包,MANIFEST.MF 也要加入,不然启动程序的时候不知道要加入这个 jar 包。增加一个manifestEntries节点:

<manifestEntries>
    
    <Class-Path>lib/aspose-words-15.8.0-jdk16.jarClass-Path>
manifestEntries>

新增于 pom.xml 的位置如图:
Word 文档转换 PDF、图片_第1张图片
拷贝 jar 包,除了 runtime 的还有刚新家的 system 包,新增一个copy-dependencies2

<execution>
     <id>copy-dependencies2id>
     <phase>packagephase>
     <goals>
         <goal>copy-dependenciesgoal>
     goals>
     <configuration>
         <outputDirectory>${project.build.directory}/liboutputDirectory>
         <includeScope>systemincludeScope>
     configuration>
 execution>

新增于 pom.xml 的位置如图:
Word 文档转换 PDF、图片_第2张图片

转换程序

import com.aspose.words.Document;
import com.aspose.words.ImageSaveOptions;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;

import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;

/**
 * ...
 * ...
 */
public class AsposeUtil {
    /**
     * Word 转 PDF
     *
     * @param wordPath Word 路径
     * @param pdfPath  PDF 路径
     */
    public static void word2pdf(String wordPath, String pdfPath) {
        AsposeUtil.getLicense();

        try (FileOutputStream os = new FileOutputStream(pdfPath)) {
            long old = System.currentTimeMillis();

            //设置一个字体目录(必须设置,否则生成的pdf乱码)下面这行代码不加的话在windows系统下生成的pdf不存在乱码问题,但是在linux系统下会乱码,linux下乱码解决方案请看后面的解决方案
            //FontSettings.setFontsFolder("/usr/share/fonts/chinese", false);
            new Document(wordPath).save(os, SaveFormat.PDF);

            System.out.println("word2pdf共耗时:" + (System.currentTimeMillis() - old) / 1000.0 + "秒");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void word2img(String wordPath, String outputDir) {
        AsposeUtil.getLicense();

        try {
            long old = System.currentTimeMillis();
            Document doc = new Document(wordPath);

            // 创建图像保存选项对象
            ImageSaveOptions options = new ImageSaveOptions(SaveFormat.JPEG);
            options.setPageCount(doc.getPageCount()); // 设置要转换的页数
//            options.setResolution(300); // 设置图像分辨率,默认为96dpi

            // 逐页转换并保存为图像
            for (int pageIndex = 0; pageIndex < doc.getPageCount(); pageIndex++) {
                String outputFileName = outputDir + "image_" + (pageIndex + 1) + ".png";
                options.setPageIndex(pageIndex);
                doc.save(outputFileName, options);
            }

            System.out.println("word2pdf共耗时:" + (System.currentTimeMillis() - old) / 1000.0 + "秒");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static final byte[] LICENSE = ("\n" +
            "    \n" +
            "        \n" +
            "            Aspose.Total for Java\n" +
            "            Aspose.Words for Java\n" +
            "        \n" +
            "        Enterprise\n" +
            "        20991231\n" +
            "        20991231\n" +
            "        8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7\n" +
            "    \n" +
            "    sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=\n" +
            "").getBytes();

    /**
     * 判断是否有授权文件 如果没有则会认为是试用版,转换的文件会有水印
     */
    public static void getLicense() {
        try (InputStream is = new ByteArrayInputStream(LICENSE)) {
            new License().setLicense(is);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
  • Aspose Jar 包下载
  • 参考文章《Java中几种office文档转pdf的方式》
  • 参考文章《Java开发中Word转PDF文件5种方案横向评测》

Apache ——iText 方案


<dependency>
    <groupId>fr.opensagres.xdocreportgroupId>
    <artifactId>org.apache.poi.xwpf.converter.pdfartifactId>
    <version>1.0.6version>
dependency>

转换程序

import fr.opensagres.xdocreport.utils.StringUtils;
import org.apache.poi.xwpf.converter.pdf.PdfConverter;
import org.apache.poi.xwpf.converter.pdf.PdfOptions;
import org.apache.poi.xwpf.usermodel.*;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;

/**
 * @author Rocca
 */
public class WordPdfUtils {

    /**
     * 将word文档, 转换成pdf, 中间替换掉变量
     *
     * @param source 源为word文档, 必须为docx文档
     * @param target 目标输出
     * @param params 需要替换的变量
     */
    public static void wordConverterToPdf(InputStream source, OutputStream target, Map<String, String> params) {
        wordConverterToPdf(source, target, null, params);
    }

    /**
     * 将word文档, 转换成pdf, 中间替换掉变量
     *
     * @param source  源为word文档, 必须为docx文档
     * @param target  目标输出
     * @param params  需要替换的变量
     * @param options PdfOptions.create().fontEncoding( "windows-1250" ) 或者其他
     */
    public static void wordConverterToPdf(InputStream source, OutputStream target, PdfOptions options, Map<String, String> params) {
        long old = System.currentTimeMillis();

        try {
            XWPFDocument doc = new XWPFDocument(source);
            paragraphReplace(doc.getParagraphs(), params);

            for (XWPFTable table : doc.getTables()) {
                for (XWPFTableRow row : table.getRows()) {
                    for (XWPFTableCell cell : row.getTableCells())
                        paragraphReplace(cell.getParagraphs(), params);
                }
            }

            PdfConverter.getInstance().convert(doc, target, options);
            System.out.println("word2pdf共耗时:" + (System.currentTimeMillis() - old) / 1000.0 + "秒");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 替换段落中内容
     */
    private static void paragraphReplace(List<XWPFParagraph> paragraphs, Map<String, String> params) {
        for (XWPFParagraph p : paragraphs) {
            for (XWPFRun r : p.getRuns()) {
                String content = r.getText(r.getTextPosition());
                if (StringUtils.isNotEmpty(content) && params.containsKey(content)) r.setText(params.get(content), 0);
            }
        }
    }

}

PDF 转图片

上述的 Aspose.Word 并不支持 PDF 转图片。要使用 Aspose PDF 转图片须使用他家的另外一个产品 Aspose.Pdf。另外有趣的是,Aspose.Word 可以直接转为图片,但由于当前需求是得到了 Pdf 加盖章和签名之后转换图片的,并不能从 Word 直接转图片。而且感觉 Word 转图片也比较慢。

我感觉 PDF 转图片比较简单,不用 Aspose 也行,——于是使用了 Apache 的 Pdfbox。


<dependency>
    <groupId>org.apache.pdfboxgroupId>
    <artifactId>pdfboxartifactId>
    <version>3.0.0version>
dependency>

你可以调整 DPI 分辨率,跟图片格式,下面例子是 gif 的。

/**
 * PDF 转图片
 *
 * @param pdfFile PDF 文件
 */
public static void pdf2Img(String pdfFile, String outputDir) {
    long old = System.currentTimeMillis();

    try (PDDocument document = Loader.loadPDF(new File(pdfFile))) {
        PDFRenderer renderer = new PDFRenderer(document);

        for (int i = 0; i < document.getNumberOfPages(); ++i) {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ImageIO.write(renderer.renderImageWithDPI(i, DPI), "gif", out);

            // 将字节数组写入到文件
            try (FileOutputStream fos = new FileOutputStream(outputDir + FileHelper.SEPARATOR + "img-" + i + ".gif")) {
                fos.write(out.toByteArray());
            }
        }

        System.out.println("pdf2img共耗时:" + (System.currentTimeMillis() - old) / 1000.0 + "秒");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

一般一份 PDF 是多页的,于是也会输出多张图片。所以你可以修改里面的文件名生成规则。

你可能感兴趣的:(word,pdf)