最近客户要做一个word,excel 文件在线预览性能,以下是实现此性能的全过程。
因为咱们用的是PHP开发我的项目,最开始想到的是用PHPoffice里的phpword来进行转换,以下是要害代码。
<?php $phpWord = \PhpOffice\PhpWord\IOFactory::load('test.doc'); $xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, "HTML"); $xmlWriter->save('test.html);
用这种办法转是能够转,然而转进去的html文件绝对原文件,失落了很多字,如果说款式和原文不一样还能够忍耐,然而内容失落,就不太好了,而且对DOC格局又无奈解决,所以这种办法,我最终抉择了放弃。
而后,我就想用python来解决这个问题,查到了python有个pydocx库能够解决word文档,于是我就装置了一下。
pip install pydocx
这个库用起来也很简略,次要代码如下:
from pydocx import PyDocX html = PyDocX.to_html("test2.doc") f = open("test.html", 'w', encoding="utf-8") f.write(html) f.close()
转换成果也还能够,除了表格款式和原文有点不一样以外,内容倒是没失落,然而有一个问题,这个库是转换docx的,对doc转换不了,咱们客户还上传挺多doc格局的文件的,于是我只好另外想方法。
查资料发现java有个poi库能够用来对word文件进行转换, Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格局档案读和写的性能。我想试一下,查资料半天,就开始写了,先Maven引入依赖:
<dependencies> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> <!-- 针对2003版本的库 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-scratchpad</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>fr.opensagres.poi.xwpf.converter.xhtml</artifactId> <version>2.0.2</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.4.3</version></dependency> </dependencies>
以下是援用他人的可用代码:
import cn.hutool.core.img.ImgUtil; import fr.opensagres.poi.xwpf.converter.xhtml.Base64EmbedImgManager; import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLConverter; import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLOptions; import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.hwpf.converter.WordToHtmlConverter; import org.apache.poi.openxml4j.util.ZipSecureFile; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.w3c.dom.Document; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.awt.image.BufferedImage; import java.io.*; /** * office转换工具测试 * */ public class OfficeConvertUtil { /** * 将word2003转换为html文件 2017-2-27 * * @param wordPath word文件门路 * @param wordName word文件名称无后缀 * @param suffix word文件后缀 * @throws IOException * @throws TransformerException * @throws ParserConfigurationException */ public static String Word2003ToHtml(String wordPath, String wordName, String suffix) throws IOException, TransformerException, ParserConfigurationException { String htmlPath = wordPath + File.separator + "html" + File.separator; String htmlName = wordName + ".html"; final String imagePath = htmlPath + "image" + File.separator; // 判断html文件是否存在,每次从新生成 File htmlFile = new File(htmlPath + htmlName); // if (htmlFile.exists()) { // return htmlFile.getAbsolutePath(); // } // 原word文档 final String file = wordPath + File.separator + wordName + suffix; InputStream input = new FileInputStream(new File(file)); HWPFDocument wordDocument = new HWPFDocument(input); WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter( DocumentBuilderFactory.newInstance().newDocumentBuilder() .newDocument()); wordToHtmlConverter.setPicturesManager((content, pictureType, suggestedName, widthInches, heightInches) -> { BufferedImage bufferedImage = ImgUtil.toImage(content); String base64Img = ImgUtil.toBase64(bufferedImage, pictureType.getExtension()); // 带图片的word,则将图片转为base64编码,保留在一个页面中 StringBuilder sb = (new StringBuilder(base64Img.length() + "data:;base64,".length()).append("data:;base64,").append(base64Img)); return sb.toString(); }); // 解析word文档 wordToHtmlConverter.processDocument(wordDocument); Document htmlDocument = wordToHtmlConverter.getDocument(); // 生成html文件下级文件夹 File folder = new File(htmlPath); if (!folder.exists()) { folder.mkdirs(); } // 生成html文件地址 OutputStream outStream = new FileOutputStream(htmlFile); DOMSource domSource = new DOMSource(htmlDocument); StreamResult streamResult = new StreamResult(outStream); TransformerFactory factory = TransformerFactory.newInstance(); Transformer serializer = factory.newTransformer(); serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8"); serializer.setOutputProperty(OutputKeys.INDENT, "yes"); serializer.setOutputProperty(OutputKeys.METHOD, "html"); serializer.transform(domSource, streamResult); outStream.close(); return htmlFile.getAbsolutePath(); } /** * 2007版本word转换成html 2017-2-27 * * @param wordPath word文件门路 * @param wordName word文件名称无后缀 * @param suffix word文件后缀 * @return * @throws IOException */ public static String Word2007ToHtml(String wordPath, String wordName, String suffix) throws IOException { ZipSecureFile.setMinInflateRatio(-1.0d); String htmlPath = wordPath + File.separator + "html" + File.separator; String htmlName = wordName + ".html"; String imagePath = htmlPath + "image" + File.separator; // 判断html文件是否存在 File htmlFile = new File(htmlPath + htmlName); // if (htmlFile.exists()) { // return htmlFile.getAbsolutePath(); // } // word文件 File wordFile = new File(wordPath + File.separator + wordName + suffix); // 1) 加载word文档生成 XWPFDocument对象 InputStream in = new FileInputStream(wordFile); XWPFDocument document = new XWPFDocument(in); // 2) 解析 XHTML配置 (这里设置IURIResolver来设置图片寄存的目录) File imgFolder = new File(imagePath); // 带图片的word,则将图片转为base64编码,保留在一个页面中 XHTMLOptions options = XHTMLOptions.create().indent(4).setImageManager(new Base64EmbedImgManager()); // 3) 将 XWPFDocument转换成XHTML // 生成html文件下级文件夹 File folder = new File(htmlPath); if (!folder.exists()) { folder.mkdirs(); } OutputStream out = new FileOutputStream(htmlFile); XHTMLConverter.getInstance().convert(document, out, options); return htmlFile.getAbsolutePath(); } public static void main(String[] args) throws Exception { System.out.println(Word2003ToHtml("D:\\tmp", "test", ".doc")); System.out.println(Word2007ToHtml("D:\\tmp", "test2", ".docx")); } }
用java 倒是转换doc格局转的挺好的,然而转换docx格局的时候,款式全乱了,我查了半天POI的文档,网上也没有哪位大佬来解决这个款式乱的问题,于是我想用python来转docx ,java来转doc,然而又感觉太麻烦。
在查了半天材料当前,我最终的解决办法如下。
还是回到了用php解决,然而不是用phpoffice来解决,而是用unocov进行转换,先装libreoffice
yum install libreoffice
而后装unocov
yum install unoconv
用以下命令就能够转换了
unoconv -f html -o test.html test.doc
-f是输入格局,-o是输入文件 最初面是输出文件,具体用法能够查相干文档,我在php里执行外部命令,生成转换好的文件当前再重定向到生成的文件下面去,因为excel 转html报错,所以我针对excel 转成了pdf.
if (file_exists($source)) { $dir = dirname($source); $ext=pathinfo($source)['extension']; if(!in_array($ext,['xls','xlsx'])){ $filetype='html'; }else $filetype='pdf'; $filename = strstr(basename($source), '.', true) . '.'.$filetype; $file = $filename; if(!file_exists('data/' . $file)){ //echo "sudo /usr/bin/unoconv -f {$filetype} -o " . '/data/web/public/data/' . $file . ' ' . '/data/web/data_manage/public/' . $source;exit; $res= shell_exec("sudo /usr/bin/unoconv -f {$filetype} -o " . '/data/web/public/data/' . $file . ' ' . '/data/web/data_manage/public/' . $source); if(!file_exists('data/' . $file)){ dump($res); exit('生成预览文件出错'); } } header("Location:".'/data/' . $file); exit(); } else exit('文件不存在');
最初,总算是把doc,docx 还有excel文件,wps文件都能预览进去,款式还是有点变动,内容没有失落,客户也还算是能承受,以上是我解决这个问题的心得,心愿能帮到大家。