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

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是一个压缩文件)freemarker生成world转PDF转SWF,加载到浏览器.解决最终浏览器加载的是xml代码的问题._第1张图片


新的解决方法:

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 包

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



1. 

	/**
	* @date 2017年11月21日 下午11:10:14 
	* @return void    返回类型
	 * @throws Exception 
	* @throws
	* @Description:
	* 	下载文档(freemarker模板)
	 */
	@RequestMapping(value="/downLoadDocx")
	@ResponseBody
	public void downLoadDocument(HttpServletResponse response, String fileName) throws Exception{
		/**
		 * 1. freemarker填充xml文件
		 * 2. xml替换docx模板中的document
		 * 3. 下载
		 */
		
		Map root = new HashMap();
		root.put("userName", "丽丽");
		root.put("sex", "2女");
		root.put("content", "这是freemarker模板引擎生成的world测试内容.");
		String preFileName = fileName;//前台传过来的文件名 test.docx
		String 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 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 配置了两个软件的安装地址.












你可能感兴趣的:(javaWeb)