freemarker生成world转PDF转SWF,加载到浏览器.解决最终浏览器加载的是xml代码的问题.

来源:互联网 发布:linux socket句柄 取值 编辑:程序博客网 时间:2024/05/19 23:10

freemarker生成world转PDF转SWF,加载到浏览器.解决最终浏览器加载的是xml代码的问题.

首先说一下需求:动态生成world,客户可在浏览器预览freemarker动态生成的world文档.

失败的解决方法: 

1. world转xml, 编辑xml,用${}替换动态改变的值。

2. freemarker动态替换${}占位符的值, 更改后缀名为doc。

3. 系统安装openoffice工具,启动openoffice服务,jodconverter 调用命令将doc转成pdf.

4. 系统安装swftools工具, 调用命令,将pdf转成swf.(很多插件支持直接加载pdf到浏览器,但是对于老版本的IE,兼容性并不好,但是swf文件基本所有浏览器都支持,所以为了老版本ie兼容性,就做了一步转swf)

5. 前台js插件flashPaper,直接加载服务器上的swf文件.

最终效果, doc和pdf文档直接双击可以打开,显示的也正常。但是flashPaper加载到浏览器则显示的是一堆xml格式代码,这个代码就是freemarker生成的doc右键文本打开后的xml代码. 经过翻阅资料,flashPaper包括很多插件不支持直接加载xml形式的doc文档(可能是我没找到正确方法,如果您有, 请给留个言,谢谢),如果非要加载,那么显示到浏览器上的就会是一推xml代码。主要原因可能是freemarker产生的doc实际上只是个xml文档,右键可打开文本查看,但是直接在桌面新建的doc,docx文档右键则打不开(实际上这样建立的doc docx是一个压缩文件)


新的解决方法:

1. 新建docx文档(07版本的), 编辑docx,需要用freemarker替换的数据用${x}代替,保存 注意: 替换变量${x}时最好一次性写完,要不可能xml文档混乱

2. 右键以压缩文件形式打开,在world/下找到document.xml文件,是freemarker需要输出的结果xml文件.格式化xml查看${}占位是否有问题,有问题

不要直接改,重新编辑world,重复1步骤开始。

3. 第2步没问题,将docx文件和导出来的xml文件复制到ftl/test下,xml重命名为docx的名字.(我建立的是javaweb项目,ftl/test是在类路径下,以方便

根据类路径可读取到这个包)

4. FreemarkerUtil.printFile 根据第三步的xml生成替换后新的xml,临时保存

5. XmlToDocxDocument.printDocx 根据第三步docx模板文件,用新的xml替换调/world下document文件,重新生成一个新的docx。

6. 系统安装openoffice工具,启动openoffice服务,jodconverter 调用命令将docx转成pdf.

4. 系统安装swftools工具, 调用命令,将pdf转成swf.(很多插件支持直接加载pdf到浏览器,但是对于老版本的IE,兼容性并不好,但是swf文件基本所

有浏览器都支持,所以为了老版本ie兼容性,就做了一步转swf)

5. 前台js插件flashPaper,直接加载服务器上的swf文件.

经测试效果良好,IE7 到 11,火狐 谷歌多种内核浏览器均可正常显示.

大致方法就是doc中包含一个xml文档,xml文档包含了所有要显示的内容,我们用freemarker替换这个xml,之后再添加压缩文件,替换回去。这样最终保持了

world的完整性,新建文档需要docx 07版的。

代码: 完整项目有附件. 点击打开链接  

需要安装的软件,资源很多 随处可下

1.  Apache_OpenOffice_4.1.4_Win_x86_install_zh-CN.exe

2.  swftools-0.9.0.exe

jar 包



1. 

/*** @date 2017年11月21日 下午11:10:14 * @return void    返回类型 * @throws Exception * @throws* @Description:* 下载文档(freemarker模板) */@RequestMapping(value="/downLoadDocx")@ResponseBodypublic void downLoadDocument(HttpServletResponse response, String fileName) throws Exception{/** * 1. freemarker填充xml文件 * 2. xml替换docx模板中的document * 3. 下载 */Map<String, Object> root = new HashMap<String, Object>();root.put("userName", "丽丽");root.put("sex", "2女");root.put("content", "这是freemarker模板引擎生成的world测试内容.");String preFileName = fileName;//前台传过来的文件名 test.docxString ftlPath = "test";//ftl下的文件夹名称String filePath = PathUtil.getDocumentPathByClassPath();//webcontent/document目录String timeFileName = FileUtil.getFilePrefixName(fileName)+(new Date().getTime())+".xml";FreemarkerUtil.printFile(FileUtil.getFilePrefixName(fileName)+".xml", root, timeFileName, filePath, ftlPath);XmlToDocxDocument.printDocx(response, filePath+timeFileName,PathUtil.getClassResources()+"/ftl/"+ftlPath+"/"+preFileName,ConfigUtil.getSwfUploadDir() + "/"+preFileName,preFileName);//删除临时freemarker生成的xml文件FileUtil.delFile(filePath+timeFileName);}

2. freemarker的代码就不贴了, 想用就看附件项目吧,看下java zip的处理XmlToDocxDocument.printDocx, 遇到document.xml文件,则替换,否则不懂,直接输出

import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.util.Enumeration;import java.util.zip.ZipEntry;import java.util.zip.ZipException;import java.util.zip.ZipFile;import java.util.zip.ZipOutputStream;import javax.servlet.http.HttpServletResponse;/** * 将freemarker替换的xml转成docx压缩文件的document.xml * @author yangwl 2017年11月23日21:56:19 * */public class XmlToDocxDocument {/*** @date 2017年11月23日 下午9:57:30 * documentFile freemarker替换之后的xml* docxTemplate docx的模板* toFilePath 导出目标文件路径* @return void    返回类型* @throws* @Description: */public static void printDocx(HttpServletResponse response, File documentFile, String docxTemplate, String toFilePath) throws ZipException, IOException {try {File docxFile = new File(docxTemplate);ZipFile zipFile = new ZipFile(docxFile);Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();ZipOutputStream zipout = new ZipOutputStream(response.getOutputStream());int len = -1;byte[] buffer = new byte[1024];while (zipEntrys.hasMoreElements()) {ZipEntry next = zipEntrys.nextElement();InputStream is = zipFile.getInputStream(next);// 把输入流的文件传到输出流中 如果是word/document.xml由我们输入zipout.putNextEntry(new ZipEntry(next.toString()));if ("word/document.xml".equals(next.toString())) {InputStream in = new FileInputStream(documentFile);while ((len = in.read(buffer)) != -1) {zipout.write(buffer, 0, len);}in.close();} else {while ((len = is.read(buffer)) != -1) {zipout.write(buffer, 0, len);}is.close();}}zipout.close();} catch (Exception e) {e.printStackTrace();}}public static void printDocx(HttpServletResponse response, String documentFile, String docxTemplate, String toFilePath, String outFileName) throws ZipException, IOException {response.reset();      response.setHeader("Content-Disposition", "attachment; filename=\"" + new String(outFileName.getBytes("gb2312"), "ISO8859-1")+ "\"");      response.setContentType("application/octet-stream;charset=UTF-8"); printDocx(response, new File(documentFile), docxTemplate, toFilePath);response.flushBuffer();}}

3. 页面显示:

 /**  * 文档预览  * world/excel/ppt 等   ->  PDF  ->  SWF   * swf兼容个版本浏览器  * 2017年11月16日14:31:16  * @param os  * @param filePath  * @throws IOException  */    @RequestMapping(value="/showDocx", method=RequestMethod.GET)    public void showOfficeFile(OutputStream os,String filePath) throws IOException {        if (!StringUtil.isEmpty(filePath)){        filePath = ConfigUtil.getSwfUploadDir() + "/" + filePath;            String swfFilePath = filePath.substring(0, filePath.lastIndexOf(".")) + ".swf";            File f = new File(swfFilePath);            boolean hasFile = true;            if (!f.exists()) {                LOGGER.info("未生成过swf文件,即将生成的SWF文件,路径为: " + swfFilePath);                hasFile = OfficeToSwf.toSwf(filePath);            }            LOGGER.info("SWF文件已生成,路径为: " + swfFilePath);            if ( hasFile ){                InputStream inputStream = null;                inputStream = new BufferedInputStream(new FileInputStream(f));                FileCopyUtils.copy(inputStream,os);                os.flush();                os.close();                inputStream.close();            }        }    }

docx-pdf

public static int office2PDF(String sourceFile, String destFile){        try {            log.debug("文件转换为PDF,[参数]SOURCEFile: " + sourceFile + "destFile: "                    + destFile);            File inputFile = new File(sourceFile);            if (!inputFile.exists()) {                return -1;// 找不到源文件, 则返回-1            }            // 如果目标路径不存在, 则新建该路径            File outputFile = new File(destFile);            if (outputFile.exists()){                    return 0;            }            if (!outputFile.getParentFile().exists()) {                outputFile.getParentFile().mkdirs();            }             // 连接服务            OpenOfficeConnection connection = OpenOfficeServer.getConnection();            connection.connect();            // convert            DocumentConverter converter = new OpenOfficeDocumentConverter(connection);                                    if (isTxt(inputFile)) {                File odtFile = isWindows(inputFile);                converter.convert(odtFile, outputFile);            } else {                DocumentFormatRegistry factory = new BasicDocumentFormatRegistry();                  DocumentFormat inputDocumentFormat = factory.getFormatByFileExtension(getExtensionName(inputFile.getAbsolutePath()));                  DocumentFormat outputDocumentFormat = factory.getFormatByFileExtension(getExtensionName(outputFile.getAbsolutePath()));                  converter.convert(inputFile, inputDocumentFormat, outputFile, outputDocumentFormat);            }            connection.disconnect();            return 0;        } catch (ConnectException e) {            log.error("openoffice 连接失败!",e);        } catch (IOException e) {            log.error("文件格式转换失败",e);        } catch (InterruptedException e) {            log.error("文件转换失败",e);            return 1;        }        return 1;    }


pdf-swf

import java.util.Properties;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.nuctech.common.util.CommandHelper;import com.nuctech.common.util.ConfigUtil;/** * pdf转swf类 */public class PdfToSwf {    private static final Logger log = LoggerFactory.getLogger(PdfToSwf.class);    /**     * pdf转swf.     *      * @param pdfPath pdf路径     * @param swfPath swf路径     * @return result     */    public static boolean pdfToSwf(String pdfPath, String swfPath) {        String command = "";        Properties properies = ConfigUtil.getProperies();        if (System.getProperty("os.name").contains("Windows")) {            command = properies.getProperty("windows.swftools.bin") + " -t " + pdfPath + " -o " + swfPath                    + " -f -s flashversion=9 ";        } else {            command = properies.getProperty("linux.swftools.bin") + " -t " + pdfPath + " -o " + swfPath                    + " -f -s flashversion=9 ";        }        log.debug("即将执行命令:" + command);        return CommandHelper.runCommand(command) == 0;    }}

注意: 启动openoffice方法 在  OpenOfficeServer的main方法里.  application.server.properties 配置了两个软件的安装地址.