Java中常用的几种DOCX转PDF方法

DOCX2PDF

成都创新互联服务项目包括南明网站建设、南明网站制作、南明网页制作以及南明网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,南明网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到南明省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!

将DOCX文档转化为PDF是项目中常见的需求之一,目前主流的方法可以分为两大类,一类是利用各种Office应用进行转换,譬如Microsoft Office、WPS以及LiberOffice,另一种是利用各种语言提供的对于Office文档读取的接口(譬如Apache POI)然后使用专门的PDFGenerator库,譬如IText进行PDF构建。总的来说,从样式上利用Office应用可以保证较好的样式,不过相对而言效率会比较低。其中Microsoft Office涉及版权,不可轻易使用(笔者所在公司就被抓包了),WPS目前使用比较广泛,不过存在超链接截断问题,即超过256个字符的超链接会被截断,LiberOffice的样式排版相对比较随意。而利用POI接口进行读取与生成的方式性能较好,适用于对于格式要求不是很高的情况。另外还有一些封装好的在线工具或者命令行工具,譬如docx2pdf与OfficeToPDF。

MicroSoft Office

本部分的核心代码如下,全部代码参考这里:

 
 
  1. private ActiveXComponent oleComponent = null;
  2. private Dispatch activeDoc = null;
  3. private final static String APP_ID = "Word.Application";
  4. // Constants that map onto Word's WdSaveOptions enumeration and that
  5. // may be passed to the close(int) method
  6. public static final int DO_NOT_SAVE_CHANGES = 0;
  7. public static final int PROMPT_TO_SAVE_CHANGES = -2;
  8. public static final int SAVE_CHANGES = -1;
  9. // These constant values determine whether or not tha application
  10. // instance will be displyed on the users screen or not.
  11. public static final boolean VISIBLE = true;
  12. public static final boolean HIDDEN = false;
  13. /**
  14.  * Create a new instance of the JacobWordSearch class using the following
  15.  * parameters.
  16.  *
  17.  * @param visibility A primitive boolean whose value will determine whether
  18.  *                   or not the Word application will be visible to the user. Pass true
  19.  *                   to display Word, false otherwise.
  20.  */
  21. public OfficeConverter(boolean visibility) {
  22.     this.oleComponent = new ActiveXComponent(OfficeConverter.APP_ID);
  23.     this.oleComponent.setProperty("Visible", new Variant(visibility));
  24. }
  25. /**
  26.  * Open ana existing Word document.
  27.  *
  28.  * @param docName An instance of the String class that encapsulates the
  29.  *                path to and name of a valid Word file. Note that there are a few
  30.  *                limitations applying to the format of this String; it must specify
  31.  *                the absolute path to the file and it must not use the single forward
  32.  *                slash to specify the path separator.
  33.  */
  34. public void openDoc(String docName) {
  35.     Dispatch disp = null;
  36.     Variant var = null;
  37.     // First get a Dispatch object referencing the Documents collection - for
  38.     // collections, think of ArrayLists of objects.
  39.     var = Dispatch.get(this.oleComponent, "Documents");
  40.     disp = var.getDispatch();
  41.     // Now call the Open method on the Documents collection Dispatch object
  42.     // to both open the file and add it to the collection. It would be possible
  43.     // to open a series of files and access each from the Documents collection
  44.     // but for this example, it is simpler to store a reference to the
  45.     // active document in a private instance variable.
  46.     var = Dispatch.call(disp, "Open", docName);
  47.     this.activeDoc = var.getDispatch();
  48. }
  49. /**
  50.  * There is more than one way to convert the document into PDF format, you
  51.  * can either explicitly use a FileConvertor object or call the
  52.  * ExportAsFixedFormat method on the active document. This method opts for
  53.  * the latter and calls the ExportAsFixedFormat method passing the name
  54.  * of the file along with the integer value of 17. This value maps onto one
  55.  * of Word's constants called wdExportFormatPDF and causes the application
  56.  * to convert the file into PDF format. If you wanted to do so, for testing
  57.  * purposes, you could add another value to the args array, a Boolean value
  58.  * of true. This would open the newly converted document automatically.
  59.  *
  60.  * @param filename
  61.  */
  62. public void publishAsPDF(String filename) {
  63.     // The code to expoort as a PDF is 17
  64.     //Object args = new Object{filename, new Integer(17), new Boolean(true)};
  65.     Object args = new Object {
  66.         filename, new Integer(17)
  67.     } ;
  68.     Dispatch.call(this.activeDoc, "ExportAsFixedFormat", args);
  69. }
  70. /**
  71.  * Called to close the active document. Note that this method simply
  72.  * calls the overloaded closeDoc(int) method passing the value 0 which
  73.  * instructs Word to close the document and discard any changes that may
  74.  * have been made since the document was opened or edited.
  75.  */
  76. public void closeDoc() {
  77.     this.closeDoc(JacobWordSearch.DO_NOT_SAVE_CHANGES);
  78. }
  79. /**
  80.  * Called to close the active document. It is possible with this overloaded
  81.  * version of the close() method to specify what should happen if the user
  82.  * has made changes to the document that have not been saved. There are three
  83.  * possible value defined by the following manifest constants;
  84.  * DO_NOT_SAVE_CHANGES - Close the document and discard any changes
  85.  * the user may have made.
  86.  * PROMPT_TO_SAVE_CHANGES - Display a prompt to the user asking them
  87.  * how to proceed.
  88.  * SAVE_CHANGES - Save the changes the user has made to the document.
  89.  *
  90.  * @param saveOption A primitive integer whose value indicates how the close
  91.  *                   operation should proceed if the user has made changes to the active
  92.  *                   document. Note that no checks are made on the value passed to
  93.  *                   this argument.
  94.  */
  95. public void closeDoc(int saveOption) {
  96.     Object args = {new Integer(saveOption)};
  97.     Dispatch.call(this.activeDoc, "Close", args);
  98. }
  99. /**
  100.  * Called once processing has completed in order to close down the instance
  101.  * of Word.
  102.  */
  103. public void quit() {
  104.     Dispatch.call(this.oleComponent, "Quit");

WPS

Java调用WPS或pdfcreator的com接口实现doc转pdf

本文的核心代码如下,完整代码查看这里:

 
 
  1.  @Override
  2.         public boolean convert(String word, String pdf) {
  3.             File pdfFile = new File(pdf);
  4.             File wordFile = new File(word);
  5.             boolean convertSuccessfully = false;
  6.             ActiveXComponent wps = null;
  7.             ActiveXComponent doc = null;
  8.             try {
  9.                 wps = new ActiveXComponent("KWPS.Application");
  10. //                Dispatch docs = wps.getProperty("Documents").toDispatch();
  11. //                Dispatch d = Dispatch.call(docs, "Open", wordFile.getAbsolutePath(), false, true).toDispatch();
  12. //                Dispatch.call(d, "SaveAs", pdfFile.getAbsolutePath(), 17);
  13. //                Dispatch.call(d, "Close", false);
  14.                 doc = wps.invokeGetComponent("Documents")
  15.                         .invokeGetComponent("Open", new Variant(wordFile.getAbsolutePath()));
  16.                 try {
  17.                     doc.invoke("SaveAs",
  18.                             new Variant(new File("C:\\Users\\lotuc\\Documents\\mmm.pdf").getAbsolutePath()),
  19.                             new Variant(17));
  20.                     convertSuccessfully = true;
  21.                 } catch (Exception e) {
  22.                     logger.warning("生成PDF失败");
  23.                     e.printStackTrace();
  24.                 }
  25.                 File saveAsFile = new File("C:\\Users\\lotuc\\Documents\\saveasfile.doc");
  26.                 try {
  27.                     doc.invoke("SaveAs", saveAsFile.getAbsolutePath());
  28.                     logger.info("成功另存为" + saveAsFile.getAbsolutePath());
  29.                 } catch (Exception e) {
  30.                     logger.info("另存为" + saveAsFile.getAbsolutePath() + "失败");
  31.                     e.printStackTrace();
  32.                 }
  33.             } finally {
  34.                 if (doc == null) {
  35.                     logger.info("打开文件 " + wordFile.getAbsolutePath() + " 失败");
  36.                 } else {
  37.                     try {
  38.                         logger.info("释放文件 " + wordFile.getAbsolutePath());
  39.                         doc.invoke("Close");
  40.                         doc.safeRelease();
  41.                     } catch (Exception e1) {
  42.                         logger.info("释放文件 " + wordFile.getAbsolutePath() + " 失败");
  43.                     }
  44.                 }
  45.                 if (wps == null) {
  46.                     logger.info("加载 WPS 控件失败");
  47.                 } else {
  48.                     try {
  49.                         logger.info("释放 WPS 控件");
  50.                         wps.invoke("Quit");
  51.                         wps.safeRelease();
  52.                     } catch (Exception e1) {
  53.                         logger.info("释放 WPS 控件失败");
  54.                     }
  55.                 }
  56.             }
  57.             return convertSuccessfully;
  58.         } 

LiberOffice

Convert Microsoft Word to PDF - using Java and LibreOffice (UNO API)

LiberOffice本身提供了一个命令行工具进行转换,在你安装好了LiberOffice之后

 
 
  1. /usr/local/bin/soffice --convert-to pdf:writer_pdf_Export /Users/lotuc/Downloads/test.doc

如果有打开的libreoffice实例, 要穿入env选项指定一个工作目录

 
 
  1. /usr/local/bin/soffice "-env:UserInstallation=file:///tmp/LibreOffice_Conversion_abc" --convert-to pdf:writer_pdf_Export /Users/lotuc/Downloads/test.doc

首先我们需要安装好LiberOffice,然后将依赖的Jar包添加到classpath中:I

 
 
  1. Install Libre Office
  2. Create a Java project in your favorite editor and add these to your class path:
  3.   [Libre Office Dir]/URE/java/juh.jar
  4.   [Libre Office Dir]/URE/java/jurt.jar
  5.   [Libre Office Dir]/URE/java/ridl.jar
  6.   [Libre Office Dir]/program/classes/unoil.jar 

然后我们需要启动一个LiberOffice进程:

 
 
  1. import java.util.Date;
  2. import java.io.File;
  3. import com.sun.star.beans.PropertyValue;
  4. import com.sun.star.comp.helper.Bootstrap;
  5. import com.sun.star.frame.XComponentLoader;
  6. import com.sun.star.frame.XDesktop;
  7. import com.sun.star.frame.XStorable;
  8. import com.sun.star.lang.XComponent;
  9. import com.sun.star.lang.XMultiComponentFactory;
  10. import com.sun.star.text.XTextDocument;
  11. import com.sun.star.uno.UnoRuntime;
  12. import com.sun.star.uno.XComponentContext;
  13. import com.sun.star.util.XReplaceDescriptor;
  14. import com.sun.star.util.XReplaceable;
  15. public class MailMergeExample {
  16. public static void main(String[] args) throws Exception {
  17.  // Initialise
  18.  XComponentContext xContext = Bootstrap.bootstrap();
  19.  XMultiComponentFactory xMCF = xContext.getServiceManager();
  20.  
  21.  Object oDesktop = xMCF.createInstanceWithContext(
  22.       "com.sun.star.frame.Desktop", xContext);
  23.  
  24.  XDesktop xDesktop = (XDesktop) UnoRuntime.queryInterface(
  25.       XDesktop.class, oDesktop); 

接下来我们需要加载目标Doc文档:

 
 
  1. // Load the Document
  2. String workingDir = "C:/projects/";
  3. String myTemplate = "letterTemplate.doc";
  4. if (!new File(workingDir + myTemplate).canRead()) {
  5.  throw new RuntimeException("Cannot load template:" + new File(workingDir + myTemplate));
  6. }
  7. XComponentLoader xCompLoader = (XComponentLoader) UnoRuntime
  8.  .queryInterface(com.sun.star.frame.XComponentLoader.class, xDesktop);
  9. String sUrl = "file:///" + workingDir + myTemplate;
  10. PropertyValue[] propertyValues = new PropertyValue[0];
  11. propertyValues = new PropertyValue[1];
  12. propertyValues[0] = new PropertyValue();
  13. propertyValues[0].Name = "Hidden";
  14. propertyValues[0].Value = new Boolean(true);
  15. XComponent xComp = xCompLoader.loadComponentFromURL(
  16.  sUrl, "_blank", 0, propertyValues);

然后我们可以使用如下方式对内容进行替换:

 
 
  1. // Search and replace
  2. XReplaceDescriptor xReplaceDescr = null;
  3. XReplaceable xReplaceable = null;
  4. XTextDocument xTextDocument = (XTextDocument) UnoRuntime
  5.   .queryInterface(XTextDocument.class, xComp);
  6. xReplaceable = (XReplaceable) UnoRuntime
  7.   .queryInterface(XReplaceable.class, xTextDocument);
  8. xReplaceDescr = (XReplaceDescriptor) xReplaceable
  9.   .createReplaceDescriptor();
  10. // mail merge the date
  11. xReplaceDescr.setSearchString("");
  12. xReplaceDescr.setReplaceString(new Date().toString());
  13. xReplaceable.replaceAll(xReplaceDescr);
  14. // mail merge the addressee
  15. xReplaceDescr.setSearchString("");
  16. xReplaceDescr.setReplaceString("Best Friend");
  17. xReplaceable.replaceAll(xReplaceDescr);
  18. // mail merge the signatory
  19. xReplaceDescr.setSearchString("");
  20. xReplaceDescr.setReplaceString("Your New Boss");
  21. xReplaceable.replaceAll(xReplaceDescr); 

然后可以输出到PDF中:

 
 
  1. // save as a PDF
  2. XStorable xStorable = (XStorable) UnoRuntime
  3.   .queryInterface(XStorable.class, xComp);
  4. propertyValues = new PropertyValue[2];
  5. propertyValues[0] = new PropertyValue();
  6. propertyValues[0].Name = "Overwrite";
  7. propertyValues[0].Value = new Boolean(true);
  8. propertyValues[1] = new PropertyValue();
  9. propertyValues[1].Name = "FilterName";
  10. propertyValues[1].Value = "writer_pdf_Export";
  11. // Appending the favoured extension to the origin document name
  12. String myResult = workingDir + "letterOutput.pdf";
  13. xStorable.storeToURL("file:///" + myResult, propertyValues);
  14. System.out.println("Saved " + myResult);

xdocreport

本文的核心代码如下,完整代码查看这里:

 
 
  1. /**
  2.  * @param inpuFile 输入的文件流
  3.  * @param outFile  输出的文件对象
  4.  * @return
  5.  * @function 利用Apache POI从输入的文件中生成PDF文件
  6.  */
  7. @SneakyThrows
  8. public static void convertWithPOI(InputStream inpuFile, File outFile) {
  9.     //从输入的文件流创建对象
  10.     XWPFDocument document = new XWPFDocument(inpuFile);
  11.     //创建PDF选项
  12.     PdfOptions pdfOptions = PdfOptions.create();//.fontEncoding("windows-1250")
  13.     //为输出文件创建目录
  14.     outFile.getParentFile().mkdirs();
  15.     //执行PDF转化
  16.     PdfConverter.getInstance().convert(document, new FileOutputStream(outFile), pdfOptions);
  17. }
  18. /**
  19.  * @param inpuFile
  20.  * @param outFile
  21.  * @param renderParams
  22.  * @function 先将渲染参数填入模板DOCX文件然后生成PDF
  23.  */
  24. @SneakyThrows
  25. public static void convertFromTemplateWithFreemarker(InputStream inpuFile, File outFile, Map renderParams) {
  26.     //创建Report实例
  27.     IXDocReport report = XDocReportRegistry.getRegistry().loadReport(
  28.             inpuFile, TemplateEngineKind.Freemarker);
  29.     //创建上下文
  30.     IContext context = report.createContext();
  31.     //填入渲染参数
  32.     renderParams.forEach((s, o) -> {
  33.         context.put(s, o);
  34.     });
  35.     //创建输出流
  36.     outFile.getParentFile().mkdirs();
  37.     //创建转化参数
  38.     Options options = Options.getTo(ConverterTypeTo.PDF).via(
  39.             ConverterTypeVia.XWPF);
  40.     //执行转化过程
  41.     report.convert(context, options, new FileOutputStream(outFile));

网站题目:Java中常用的几种DOCX转PDF方法
本文来源:http://www.mswzjz.com/qtweb/news20/195820.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联