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.
5. // Constants that map onto Word's WdSaveOptions enumeration and that
6. // may be passed to the close(int) method
7. public static final int DO_NOT_SAVE_CHANGES = 0;
8. public static final int PROMPT_TO_SAVE_CHANGES = -2;
9. public static final int SAVE_CHANGES = -1;
10.
11. // These constant values determine whether or not tha application
12. // instance will be displyed on the users screen or not.
13. public static final boolean VISIBLE = true;
14. public static final boolean HIDDEN = false;
15.
16. /**
17.  * Create a new instance of the JacobWordSearch class using the following
18.  * parameters.
19.  *
20.  * @param visibility A primitive boolean whose value will determine whether
21.  *                  or not the Word application will be visible to the user. Pass true
22.  *                  to display Word, false otherwise.
23.  */
24. public OfficeConverter(boolean visibility) {
25.    this.oleComponent = new ActiveXComponent(OfficeConverter.APP_ID);
26.    this.oleComponent.setProperty("Visible", new Variant(visibility));
27. }
28.
29. /**
30.  * Open ana existing Word document.
31.  *
32.  * @param docName An instance of the String class that encapsulates the
33.  *                path to and name of a valid Word file. Note that there are a few
34.  *                limitations applying to the format of this String; it must specify
35.  *                the absolute path to the file and it must not use the single forward
36.  *                slash to specify the path separator.
37.  */
38. public void openDoc(String docName) {
39.    Dispatch disp = null;
40.    Variant var = null;
41.    // First get a Dispatch object referencing the Documents collection - for
42.    // collections, think of ArrayLists of objects.
43.    var = (this.oleComponent, "Documents");
44.    disp = Dispatch();
45.    // Now call the Open method on the Documents collection Dispatch object
46.    // to both open the file and add it to the collection. It would be possible
47.    // to open a series of files and access each from the Documents collection
48.    // but for this example, it is simpler to store a reference to the
49.    // active document in a private instance variable.
50.    var = Dispatch.call(disp, "Open", docName);
51.    this.activeDoc = Dispatch();
52. }
53.
54. /**
55.  * There is more than one way to convert the document into PDF format, you
56.  * can either explicitly use a FileConvertor object or call the
57.  * ExportAsFixedFormat method on the active document. This method opts for
58.  * the latter and calls the ExportAsFixedFormat method passing the name
59.  * of the file along with the integer value of 17. This value maps onto one
getsavefilename
60.  * of Word's constants called wdExportFormatPDF and causes the application
61.  * to convert the file into PDF format. If you wanted to do so, for testing
62.  * purposes, you could add another value to the args array, a Boolean value
63.  * of true. This would open the newly converted document automatically.
64.  *
65.  * @param filename
66.  */
67. public void publishAsPDF(String filename) {
68.    // The code to expoort as a PDF is 17
69.    //Object args = new Object{filename, new Integer(17), new Boolean(true)};
70.    Object args = new Object {
71.        filename, new Integer(17)
72.    } ;
73.    Dispatch.call(this.activeDoc, "ExportAsFixedFormat", args);
74. }
75.
76. /**
77.  * Called to close the active document. Note that this method simply
78.  * calls the overloaded closeDoc(int) method passing the value 0 which
79.  * instructs Word to close the document and discard any changes that may
80.  * have been made since the document was opened or edited.
82. public void closeDoc() {
83.    this.closeDoc(JacobWordSearch.DO_NOT_SAVE_CHANGES);
84. }
85.
86. /**
87.  * Called to close the active document. It is possible with this overloaded
88.  * version of the close() method to specify what should happen if the user
89.  * has made changes to the document that have not been saved. There are three
90.  * possible value defined by the following manifest constants;
91.  * DO_NOT_SAVE_CHANGES - Close the document and discard any changes
92.  * the user may have made.
93.  * PROMPT_TO_SAVE_CHANGES - Display a prompt to the user asking them
94.  * how to proceed.
95.  * SAVE_CHANGES - Save the changes the user has made to the document.
96.  *
97.  * @param saveOption A primitive integer whose value indicates how the close
98.  *                  operation should proceed if the user has made changes to the active
99.  *                  document. Note that no checks are made on the value passed to 100.  *                  this argument.
101.  */
102. public void closeDoc(int saveOption) {
103.    Object args = {new Integer(saveOption)};
104.    Dispatch.call(this.activeDoc, "Close", args);
105. }
106.
107. /**
108.  * Called once processing has completed in order to close down the instance 109.  * of Word.
110.  */
111. public void quit() {
112.    Dispatch.call(this.oleComponent, "Quit");
113. }
WPS
本⽂的核⼼代码如下,完整代码查看这⾥:
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.
7.            ActiveXComponent wps = null;
8.            ActiveXComponent doc = null;
9.
11.            try {
12.                wps = new ActiveXComponent("KWPS.Application");
13.
14. //                Dispatch docs = Property("Documents").toDispatch();
15. //                Dispatch d = Dispatch.call(docs, "Open", AbsolutePath(), false, true).toDispatch();
16. //                Dispatch.call(d, "SaveAs", AbsolutePath(), 17);
17. //                Dispatch.call(d, "Close", false);
18.
19.                doc = wps.invokeGetComponent("Documents")
20.                        .invokeGetComponent("Open", new AbsolutePath()));
21.
22.                try {
23.                    doc.invoke("SaveAs",
24.                            new Variant(new File("C:\\Users\\lotuc\\Documents\\mmm.pdf").getAbsolutePath()),
25.                            new Variant(17));
26.                    convertSuccessfully = true;
27.                } catch (Exception e) {
28.                    logger.warning("⽣成PDF失败");
29.                    e.printStackTrace();
30.                }
31.
32.                File saveAsFile = new File("C:\\Users\\lotuc\\Documents\\saveasfile.doc");
33.                try {
34.                    doc.invoke("SaveAs", AbsolutePath());
35.                    logger.info("成功另存为" + AbsolutePath());
36.                } catch (Exception e) {
37.                    logger.info("另存为" + AbsolutePath() + "失败");
38.                    e.printStackTrace();
39.                }
40.            } finally {
41.                if (doc == null) {
42.                    logger.info("打开⽂件 " + AbsolutePath() + " 失败");
43.                } else {
44.                    try {
45.                        logger.info("释放⽂件 " + AbsolutePath());
46.                        doc.invoke("Close");
47.                        doc.safeRelease();
48.                    } catch (Exception e1) {
49.                        logger.info("释放⽂件 " + AbsolutePath() + " 失败");
50.                    }
51.                }
52.
53.                if (wps == null) {
54.                    logger.info("加载 WPS 控件失败");
55.                } else {
56.                    try {
57.                        logger.info("释放 WPS 控件");
58.                        wps.invoke("Quit");
59.                        wps.safeRelease();
60.                    } catch (Exception e1) {
61.                        logger.info("释放 WPS 控件失败");
62.                    }
63.                }
64.            }
65.
66.            return convertSuccessfully;
67.        }
LiberOffice
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.
3. Create a Java project in your favorite editor and add these to your class path:
4.  [Libre Office Dir]/URE/java/juh.jar
5.  [Libre Office Dir]/URE/java/jurt.jar
6.  [Libre Office Dir]/URE/java/ridl.jar
7.  [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.starp.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.XTextDocument;
11. import com.sun.star.uno.UnoRuntime;

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。