我该如何将Word文档转换为PDF文件?

55

如何将包含各种内容(例如表格)的Word文档转换为PDF格式?在尝试使用iText时,生成的PDF文件与原始文档不同。有没有开源API/库可供使用,而不是调用可执行文件?

9个回答

57
这是一项非常困难的任务,如果您想要完美的结果(不使用Word是不可能的),那么它会更加困难,因此,我认为完全由Java编写且开源的API数量为零(更新:我错了,请参见下文)。
您的基本选择如下:
  1. 使用JNI / C# Web服务 /等脚本MS Office(仅用于100%完美的结果)
  2. 使用可用的API脚本Open Office(90%+完美)
  3. 使用Apache POI和iText(非常庞大的工作,永远不会完美)。
更新-2016-02-11 以下是我关于此主题的博客文章的简化副本,概述了现有支持Java中Word转PDF的产品。 将Microsoft Office(Word、Excel)文档转换为PDFs 我知道三种可以呈现Office文档的产品: yeokm1/docs-to-pdf-converter 不定期维护,纯Java,开源 将多个库组合在一起执行转换。

xdocreport 活跃开发,纯Java,开源 它是一个Java API,用于合并使用MS Office(docx)或OpenOffice(odt),LibreOffice(odt)创建的XML文档,并与Java模型一起生成报告,如果需要,可以将其转换为其他格式(PDF,XHTML等)。

Snowbound Imaging SDK 闭源,纯Java Snowbound似乎是一个100%的Java解决方案,售价超过2500美元。它包含有关如何在评估下载中转换文档的示例。

OpenOffice API 开源,非纯Java - 需要安装Open Office OpenOffice是一个本地办公套件,支持Java API。这支持读取Office文档和编写PDF文档。SDK包含一个文档转换示例(examples/java/DocumentHandling/DocumentConverter.java)。要编写PDF,您需要传递“writer_pdf_Export”写入器,而不是“MS Word 97”写入器。 或者您可以使用封装API JODConverter

JDocToPdf - 已于2016-02-11停止更新 使用Apache POI读取Word文档并使用iText编写PDF。完全免费,100% Java,但有一些限制


mlk,你能详细说明第一种选择吗?对于我的情况,我更倾向于调用微软制造的API,即使涉及使用JNI,以便获得最佳的PDF渲染效果。 - kwikness
1
我稍微研究了一下这个问题(http://www.suodenjoki.dk/us/productions/articles/word2pdf.htm)。我不建议使用这种方法,微软也同意。Word并不是为自动化设计的。 - Michael Lloyd Lee mlk
1
如果我要做这件事,我会使用Open Office。 - Michael Lloyd Lee mlk
Docx4j 可以使用 FO + FOP 处理 docx。但是从 v3.3 开始,它默认使用我们更高质量的商业转换器,可以同时处理 doc 和 docx,并且您可以在 http://converter-eval.plutext.com/ 上进行试用。 - JasonPlutext
1
我更喜欢使用 https://gotenberg.dev/docs/about,它提供了强大和完美的API来将 DOCX 文件转换为 PDF。它还提供了Docker容器,可以在我们的环境中运行 :-) - srr7
显示剩余3条评论

9

Docx4j是开源的API,最适合将Docx转换为PDF,无需考虑任何对齐或字体问题。

Maven依赖项

<dependency>
    <groupId>org.docx4j</groupId>
    <artifactId>docx4j-JAXB-Internal</artifactId>
    <version>8.0.0</version>
</dependency>
<dependency>
    <groupId>org.docx4j</groupId>
    <artifactId>docx4j-JAXB-ReferenceImpl</artifactId>
    <version>8.0.0</version>
</dependency>
<dependency>
    <groupId>org.docx4j</groupId>
    <artifactId>docx4j-JAXB-MOXy</artifactId>
    <version>8.0.0</version>
</dependency>
<dependency>
    <groupId>org.docx4j</groupId>
    <artifactId>docx4j-export-fo</artifactId>
    <version>8.0.0</version>
</dependency>

代码:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;

import org.docx4j.Docx4J;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;

public class DocToPDF {

    public static void main(String[] args) {
        
        try {
            InputStream templateInputStream = new FileInputStream("D:\\\\Workspace\\\\New\\\\Sample.docx");
            WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(templateInputStream);
            MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();

            String outputfilepath = "D:\\\\Workspace\\\\New\\\\Sample.pdf";
            FileOutputStream os = new FileOutputStream(outputfilepath);
            Docx4J.toPDF(wordMLPackage,os);
            os.flush();
            os.close();
        } catch (Throwable e) {

            e.printStackTrace();
        } 
    }

}

8
您可以使用JODConverter来完成这个任务。 它可以用于在不同的办公格式之间转换文档,例如:
  1. Microsoft Office到OpenDocument,反之亦然
  2. 任何格式到PDF
  3. 还支持许多其他的转换方式
  4. 它也可以将MS Office 2007文档转换为PDF,并支持几乎所有格式
更多关于JODConverter的详细信息,请见: http://www.artofsolving.com/opensource/jodconverter

6
已经到了2019年,我简直不敢相信在Java世界中仍然没有最简单和最便捷的方法将最流行的Micro$oft Word文档转换为Adobe PDF格式。
我几乎尝试了以上答案提到的每种方法,我发现能满足我的要求的最好且唯一的方法是使用OpenOffice或LibreOffice。实际上,我并不确切知道它们之间的区别,似乎两者都提供"soffice"命令行。
我的需求是:
1. 它必须在Linux上运行,更具体地说是在CentOS上,不能在Windows上运行,因此我们不能在其上安装Microsoft Office; 2. 它必须支持中文字符,因此ISO-8859-1字符编码不是一个选择,必须支持Unicode。
首先想到的是"doc-to-pdf-converter",但它缺乏维护,上次更新是4年前,我不会使用一个无人维护的解决方案。"Xdocreport"似乎是一个有前途的选择,但它只能转换"docx",而不能转换对我来说必不可少的"doc"二进制文件。使用Java调用OpenOffice API似乎不错,但对于这样一个简单的要求来说太复杂了。
最后我找到了最好的解决方案:使用OpenOffice命令行完成这项工作。
Runtime.getRuntime().exec("soffice --convert-to pdf -outdir . /path/some.doc");

我一直相信代码越短越好(当然,它必须是易懂的),就是这样。


考虑到开源办公套件与Word不是100%兼容,这是否可行? - JohnC
如果您的Word文档包含一些VBA脚本,这些脚本将在文档打开后更改某些内容,我猜OpenOffice可能无法正确处理。但在大多数情况下,如果您的Word文档只是一些文本和图片,那应该没有问题。 - Zhang Buzz
我希望这是2020年最简单的转换方式 https://dev59.com/uHA75IYBdhLWcg3w794Y#65403145 - Sathiamoorthy

5

请查看github上的docs-to-pdf-converter。这是一个专门用于将文档转换为PDF的轻量级解决方案。

为什么?

我想要一个简单的程序,可以将Microsoft Office文档转换为PDF,但不需要像LibreOffice或昂贵的专有解决方案那样依赖其他软件。考虑到将每个单独格式的代码和库都散布在Web上,我决定将所有这些解决方案合并成一个单一的程序。在此过程中,我还决定添加ODT支持,因为我也遇到了该代码。


1
这个项目已经不再维护,也没有测试,因此分叉它是值得商榷的。 - Joseph

3
您可以使用Cloudmersive原生Java库。它免费提供每月最多50,000次转换,并且在我的经验中,比其他像iText或基于Apache POI的方法具有更高的保真度。文档实际上看起来与它们在Microsoft Word中的样子相同,这对我来说非常重要。顺便说一句,它还可以将XLSX、PPTX和传统的DOC、XLS和PPT转换为PDF。
以下是代码示例,首先添加您的导入:
import com.cloudmersive.client.invoker.ApiClient;
import com.cloudmersive.client.invoker.ApiException;
import com.cloudmersive.client.invoker.Configuration;
import com.cloudmersive.client.invoker.auth.*;
import com.cloudmersive.client.ConvertDocumentApi;

然后将文件转换:

ApiClient defaultClient = Configuration.getDefaultApiClient();

// Configure API key authorization: Apikey
ApiKeyAuth Apikey = (ApiKeyAuth) defaultClient.getAuthentication("Apikey");
Apikey.setApiKey("YOUR API KEY");

ConvertDocumentApi apiInstance = new ConvertDocumentApi();
File inputFile = new File("/path/to/input.docx"); // File to perform the operation on.
try {
  byte[] result = apiInstance.convertDocumentDocxToPdf(inputFile);
  System.out.println(result);
} catch (ApiException e) {
  System.err.println("Exception when calling ConvertDocumentApi#convertDocumentDocxToPdf");
e.printStackTrace();
}

你可以从门户网站免费获取文档转换API密钥。 点击此处

它内部使用itext吗? - Sanjay Sahani

1

使用 JACOB 调用 Office Word 是一个完美的解决方案。但它只支持在 Windows 平台上,因为需要安装 Office Word

  1. Download JACOB archive (the latest version is 1.19);
  2. Add jacob.jar to your project classpath;
  3. Add jacob-1.19-x32.dll or jacob-1.19-x64.dll (depends on your jdk version) to ...\Java\jdk1.x.x_xxx\jre\bin
  4. Using JACOB API call Office Word to convert doc/docx to pdf.

    public void convertDocx2pdf(String docxFilePath) {
    File docxFile = new File(docxFilePath);
    String pdfFile = docxFilePath.substring(0, docxFilePath.lastIndexOf(".docx")) + ".pdf";
    
    if (docxFile.exists()) {
        if (!docxFile.isDirectory()) { 
            ActiveXComponent app = null;
    
            long start = System.currentTimeMillis();
            try {
                ComThread.InitMTA(true); 
                app = new ActiveXComponent("Word.Application");
                Dispatch documents = app.getProperty("Documents").toDispatch();
                Dispatch document = Dispatch.call(documents, "Open", docxFilePath, false, true).toDispatch();
                File target = new File(pdfFile);
                if (target.exists()) {
                    target.delete();
                }
                Dispatch.call(document, "SaveAs", pdfFile, 17);
                Dispatch.call(document, "Close", false);
                long end = System.currentTimeMillis();
                logger.info("============Convert Finished:" + (end - start) + "ms");
            } catch (Exception e) {
                logger.error(e.getLocalizedMessage(), e);
                throw new RuntimeException("pdf convert failed.");
            } finally {
                if (app != null) {
                    app.invoke("Quit", new Variant[] {});
                }
                ComThread.Release();
            }
        }
    }
    

    }


JACOB已经迁移到GitHub https://github.com/freemansoft/jacob-project/releases - icrovett

1

我同意那些将OpenOffice列为具有Java API的高保真度导入/导出Word/PDF文档的工具,并且它还可以跨平台使用。OpenOffice的导入/导出过滤器非常强大,在转换为各种格式(包括PDF)时能够保留大部分格式。DocmosisJODReports的附加值使得生活比直接学习OpenOffice API更容易,因为UNO API的风格和与崩溃相关的错误可能会带来挑战。


0

unoconv是一个在UNIX系统中运行的Python工具。 当我使用Java调用UNIX shell时,它对我来说非常完美。我的源代码:UnoconvTool.java。据说JODConverter和unoconv都使用开放办公室/自由办公室。

docx4j/docxreport、POI、PDFBox都很好,但它们在转换中缺少一些格式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接