`

(转载)将现有数据导出为制定模板的 word 文件 (word导出、将图片导出到word)

阅读更多

 最近项目相关功能中需要导出word文件,不过之前已经有同事完成了相关功能。他的实现方式如下:

将已准备好的word模板另存为html格式,然后将导出后的html格式化后直接拷贝到jsp,并在jsp开始位置加入
Java代码 复制代码
  1. <%@page contentType="application/msword; charset=UTF-8" %>  
<%@page contentType="application/msword; charset=UTF-8" %>
 。之后,使用系统数据替换jsp中对应的内容即可。

    导出时,只需要将导出动作指向到该jsp页面,即可自动下载为word格式的文件。

 

    经测试,通过以上方式导出word,打开文件后会提示某些文件丢失,导致word格式不完整,且打开后默认显示为html样式的问题。问题很诡异,因为之前同时做的时候没有发现这样的情况,而现在发现后也没有找到解决办法。-_-!!无奈就放弃了这个做法(项目时间原因。。。大家可以参考此方法,完全可行,就是不知道我们的问题出在哪。。。)。

 

    word导出

    下面是目前项目使用的导出方法,这个方法与上面的方法类似,是将wrod以xml格式进行处理,实现方式如下:

    1.文本内容导出

    将已准备好的word模板另存为xml格式(可选择2003xml格式,提高兼容性),然后将导出的xml格式化后直接拷贝到jsp,并在jsp开始位置加入

Java代码 复制代码
  1. <%@page contentType="application/msword; charset=UTF-8" %>  
<%@page contentType="application/msword; charset=UTF-8" %>

    ,导出方式与html格式的一样。 xml格式的内容看起来更规范,也方便进行循环等数据操作。(关键是使用此方法后,word导出格式完全正常了^_^)

    注:xml格式的word文件中首行内容

Xml代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>  
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

   必须保证在jsp文件的第一行,否则导出的word将无法打开,提示格式错误。

 

    2.图片导出到word

    貌似这方面的资料比较少,查了很多资料才找到的-_-!!,实现方式如下:

 

    将一个包含图片的word文件另存为xml格式,然后打开xml文件,可找到类似代码如下

Xml代码 复制代码
  1. <w:pict>  
  2.   <v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">  
  3.   <v:stroke joinstyle="miter" />  
  4.   <v:formulas>  
  5.     <v:f eqn="if lineDrawn pixelLineWidth 0" />  
  6.     <v:f eqn="sum @0 1 0" />  
  7.     <v:f eqn="sum 0 0 @1" />  
  8.     <v:f eqn="prod @2 1 2" />  
  9.     <v:f eqn="prod @3 21600 pixelWidth" />  
  10.     <v:f eqn="prod @3 21600 pixelHeight" />  
  11.     <v:f eqn="sum @0 0 1" />  
  12.     <v:f eqn="prod @6 1 2" />  
  13.     <v:f eqn="prod @7 21600 pixelWidth" />  
  14.     <v:f eqn="sum @8 21600 0" />  
  15.     <v:f eqn="prod @7 21600 pixelHeight" />  
  16.     <v:f eqn="sum @10 21600 0" />  
  17.   </v:formulas>  
  18.   <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect" />  
  19.   <o:lock v:ext="edit" aspectratio="t" />  
  20.   </v:shapetype>  
  21.   <w:binData w:name="wordml://02000001.jpg" xml:space="preserve">  
  22.     /9j/4AAQSkZJRgABAgEAYABgAAD/7RguUGhvdG9zaG9wIDMuMAA4QklNA+0KUmVzb2x1dGlvbgAAAAAQAGAAAAABAAEAYAAAAAEAAThCSU0EDRhGWCBHbG9iYWwgTGlnaHRpbmcgQW5nbGUAAAAABAAA   
  23. AHg4QklNBBkSRlggR2xvYmFsIEFsdGl0dWRlAAAAAAQAAAAeOEJJTQPzC1ByaW50IEZsYWdzAAAA   
  24. CQAAAAAAAAAAAQA4QklNBAoOQ29weXJpZ2h0IEZsYWcAAAAAAQAAOEJJTScQFEphcGFuZXNlIFBy   
  25. ...   
  26. ...   
  27. ...   
  28.   </w:binData>  
  29.   <v:shape id="_x0000_i1025" type="#_x0000_t75" <v:shape id="_x0000_i1025" type="#_x0000_t75"  
  30.     <v:imagedata src="wordml://02000001.jpg" o:title="Water lilies" />  
  31.   </v:shape>  
  32. </w:pict>  
<w:pict>
  <v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
  <v:stroke joinstyle="miter" />
  <v:formulas>
    <v:f eqn="if lineDrawn pixelLineWidth 0" />
    <v:f eqn="sum @0 1 0" />
    <v:f eqn="sum 0 0 @1" />
    <v:f eqn="prod @2 1 2" />
    <v:f eqn="prod @3 21600 pixelWidth" />
    <v:f eqn="prod @3 21600 pixelHeight" />
    <v:f eqn="sum @0 0 1" />
    <v:f eqn="prod @6 1 2" />
    <v:f eqn="prod @7 21600 pixelWidth" />
    <v:f eqn="sum @8 21600 0" />
    <v:f eqn="prod @7 21600 pixelHeight" />
    <v:f eqn="sum @10 21600 0" />
  </v:formulas>
  <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect" />
  <o:lock v:ext="edit" aspectratio="t" />
  </v:shapetype>
  <w:binData w:name="wordml://02000001.jpg" xml:space="preserve">
    /9j/4AAQSkZJRgABAgEAYABgAAD/7RguUGhvdG9zaG9wIDMuMAA4QklNA+0KUmVzb2x1dGlvbgAAAAAQAGAAAAABAAEAYAAAAAEAAThCSU0EDRhGWCBHbG9iYWwgTGlnaHRpbmcgQW5nbGUAAAAABAAA
AHg4QklNBBkSRlggR2xvYmFsIEFsdGl0dWRlAAAAAAQAAAAeOEJJTQPzC1ByaW50IEZsYWdzAAAA
CQAAAAAAAAAAAQA4QklNBAoOQ29weXJpZ2h0IEZsYWcAAAAAAQAAOEJJTScQFEphcGFuZXNlIFBy
...
...
...
  </w:binData>
  <v:shape id="_x0000_i1025" type="#_x0000_t75" <v:shape id="_x0000_i1025" type="#_x0000_t75"
    <v:imagedata src="wordml://02000001.jpg" o:title="Water lilies" />
  </v:shape>
</w:pict>

    注意

Xml代码 复制代码
  1. <w:binData w:name="wordml://02000001.jpg" xml:space="preserve">  
  2. ...   
  3. ...   
  4. </w:binData>  
<w:binData w:name="wordml://02000001.jpg" xml:space="preserve">
...
...
</w:binData>

    之间的内容,此标签所包含的内容便是我们要插入图片的Base64编码,我们需要做的就是将需要导出的图片转换为base64编码,然后将编码嵌入到对应的标签内即可。

 

    实例代码(由于xml的内容太多,所以这里只给出主要内容,其他省略)

 

Jsp代码代码 复制代码
  1. <%@page contentType="application/msword; charset=UTF-8" %><?xml version="1.0" encoding="UTF-8" standalone="yes"?>   
  2. <?mso-application progid="Word.Document"?>   
  3. <w:wordDocument ... ... xml:space="preserve">   
  4. ...   
  5. ...   
  6. ...   
  7.   <w:body>   
  8.     ...   
  9.     ...   
  10.     ...   
  11.     <%    
  12.         //將图片转换为Base64码    
  13.         String picBase64 = ToolKit.getImgBase64CodeStr(path);   
  14.      %>   
  15.     <w:tbl>   
  16.       <w:tblPr>   
  17.         <w:tblW w:w="0" w:type="auto" />   
  18.         <w:tblLook w:val="04A0" />   
  19.       </w:tblPr>   
  20.       <w:tblGrid>   
  21.         <w:gridCol w:w="4536" />   
  22.       </w:tblGrid>   
  23.       <w:tr wsp:rsidR="001023FB" wsp:rsidRPr="00E92BAD" wsp:rsidTr="003848F5">   
  24.         <w:tc>   
  25.           <w:tcPr>   
  26.             <w:tcW w:w="4536" w:type="dxa" />   
  27.             <w:vAlign w:val="center" />   
  28.           </w:tcPr>   
  29.         ...   
  30.         ...   
  31.         <w:pict>   
  32.           <v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" xath="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">   
  33.           <v:stroke joinstyle="miter" />   
  34.           <v:formulas>   
  35.             <v:f eqn="if lineDrawn pixelLineWidth 0" />   
  36.             <v:f eqn="sum @0 1 0" />   
  37.             <v:f eqn="sum 0 0 @1" />   
  38.             <v:f eqn="prod @2 1 2" />   
  39.             <v:f eqn="prod @3 21600 pixelWidth" />   
  40.             <v:f eqn="prod @3 21600 pixelHeight" />   
  41.             <v:f eqn="sum @0 0 1" />   
  42.             <v:f eqn="prod @6 1 2" />   
  43.             <v:f eqn="prod @7 21600 pixelWidth" />   
  44.             <v:f eqn="sum @8 21600 0" />   
  45.             <v:f eqn="prod @7 21600 pixelHeight" />   
  46.             <v:f eqn="sum @10 21600 0" />   
  47.           </v:formulas>   
  48.           <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect" />   
  49.           <o:lock v:ext="edit" aspectratio="t" />   
  50.           </v:shapetype>   
  51.           <w:binData w:name="wordml://02000001.jpg" xml:space="preserve"><%=picBase64%></w:binData>   
  52.            <v:shape id="_x0000_i1025" type="#_x0000_t75" <v:shape id="_x0000_i1025" type="#_x0000_t75"  
  53.            <v:imagedata src="wordml://02000001.jpg" o:title="Water lilies" />   
  54.          </v:shape>   
  55.        </w:pict>   
  56.        ...   
  57.        ...   
  58.        ...   
  59.   </w:body>   
  60. </w:wordDocument>  
<%@page contentType="application/msword; charset=UTF-8" %><?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?mso-application progid="Word.Document"?>
<w:wordDocument ... ... xml:space="preserve">
...
...
...
  <w:body>
    ...
    ...
    ...
    <% 
        //將图片转换为Base64码 
        String picBase64 = ToolKit.getImgBase64CodeStr(path);
     %>
    <w:tbl>
      <w:tblPr>
        <w:tblW w:w="0" w:type="auto" />
        <w:tblLook w:val="04A0" />
      </w:tblPr>
      <w:tblGrid>
        <w:gridCol w:w="4536" />
      </w:tblGrid>
      <w:tr wsp:rsidR="001023FB" wsp:rsidRPr="00E92BAD" wsp:rsidTr="003848F5">
        <w:tc>
          <w:tcPr>
            <w:tcW w:w="4536" w:type="dxa" />
            <w:vAlign w:val="center" />
          </w:tcPr>
        ...
        ...
        <w:pict>
          <v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" xath="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
          <v:stroke joinstyle="miter" />
          <v:formulas>
            <v:f eqn="if lineDrawn pixelLineWidth 0" />
            <v:f eqn="sum @0 1 0" />
            <v:f eqn="sum 0 0 @1" />
            <v:f eqn="prod @2 1 2" />
            <v:f eqn="prod @3 21600 pixelWidth" />
            <v:f eqn="prod @3 21600 pixelHeight" />
            <v:f eqn="sum @0 0 1" />
            <v:f eqn="prod @6 1 2" />
            <v:f eqn="prod @7 21600 pixelWidth" />
            <v:f eqn="sum @8 21600 0" />
            <v:f eqn="prod @7 21600 pixelHeight" />
            <v:f eqn="sum @10 21600 0" />
          </v:formulas>
          <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect" />
          <o:lock v:ext="edit" aspectratio="t" />
          </v:shapetype>
          <w:binData w:name="wordml://02000001.jpg" xml:space="preserve"><%=picBase64%></w:binData>
           <v:shape id="_x0000_i1025" type="#_x0000_t75" <v:shape id="_x0000_i1025" type="#_x0000_t75"
           <v:imagedata src="wordml://02000001.jpg" o:title="Water lilies" />
         </v:shape>
       </w:pict>
       ...
       ...
       ...
  </w:body>
</w:wordDocument>

 

 

Java代码 复制代码
  1. /**  
  2.  * 获取图片的Base64编码  
  3.  * @param imgFilePath   图片路径  
  4.  * @return  
  5.  */  
  6. public static String getImgBase64CodeStr(String imgFilePath) {   
  7.     byte[] data = null;   
  8.     try {    
  9.         InputStream in = new FileInputStream(imgFilePath);    
  10.         data = new byte[in.available()];    
  11.         in.read(data);    
  12.         in.close();    
  13.     } catch (IOException e) {    
  14.         e.printStackTrace();    
  15.     }    
  16.     // 对字节数组Base64编码    
  17.     BASE64Encoder encoder = new BASE64Encoder();    
  18.     return encoder.encode(data);// 返回Base64编码后的字节字符串   
  19. }  
	/**
	 * 获取图片的Base64编码
	 * @param imgFilePath	图片路径
	 * @return
	 */
	public static String getImgBase64CodeStr(String imgFilePath) {
		byte[] data = null;
		try { 
			InputStream in = new FileInputStream(imgFilePath); 
			data = new byte[in.available()]; 
			in.read(data); 
			in.close(); 
		} catch (IOException e) { 
			e.printStackTrace(); 
		} 
		// 对字节数组Base64编码 
		BASE64Encoder encoder = new BASE64Encoder(); 
		return encoder.encode(data);// 返回Base64编码后的字节字符串
	}

 

    如此便可将任意图片导出到word中。

 

 

    3.导出中常见的问题及解决方法

 

       (1)导出时抛出如下异常:

Java代码 复制代码
  1. org.apache.jasper.JasperException: Unable to compile class for JSP:    
  2.   
  3. An error occurred at line: 29 in the generated java file   
  4. The code of method _jspService(HttpServletRequest, HttpServletResponse) is exceeding the 65535 bytes limit   
  5.   
  6. Stacktrace:   
  7.     at org.apache.jasper.compiler.DefaultErrorHandler.javacError(DefaultErrorHandler.java:92)   
  8.     at org.apache.jasper.compiler.ErrorDispatcher.javacError(ErrorDispatcher.java:330)   
  9. ...   
  10. ...  
org.apache.jasper.JasperException: Unable to compile class for JSP: 

An error occurred at line: 29 in the generated java file
The code of method _jspService(HttpServletRequest, HttpServletResponse) is exceeding the 65535 bytes limit

Stacktrace:
	at org.apache.jasper.compiler.DefaultErrorHandler.javacError(DefaultErrorHandler.java:92)
	at org.apache.jasper.compiler.ErrorDispatcher.javacError(ErrorDispatcher.java:330)
...
...

 

 

        此问题的主要原因是JAVA文件中对方法有一个大小限制,最大不超过64K,而我的JSP中编译成SERVLET代码的时候就变成了service方法,这个方法的大小不能超过64K,当JSP文件太大的时候编译成的serviece方法自然就超过了。(如果word模板的内容比较多或比较复杂,另存的xml文件就会非常大,当拷贝到jsp中进行编译的时候便会出现此问题)

 

        解决方法就是将jsp文件通过<jsp:include>标签拆分为多个文件(这里不能使用<%@INCLUDE%>,具体原因请查看这两个标签的区别:http://lynn-hou.iteye.com/blog/689594)

 

       (2)导出后提示无法打开文件,详细信息为: text/xml 声明只能出现在输入的开始位置

       问题中已经说的很明白了,我在上面已经提示过了

Xml代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>  
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

       必须放在jsp文件的第一行。如果此代码前还需要放其他内容,将所有内容放都放在第一行,不换行就可以了。例如

Xml代码 复制代码
  1. <%@page contentType="application/msword; charset=UTF-8" %><?xml version="1.0" encoding="UTF-8" standalone="yes"?>  
<%@page contentType="application/msword; charset=UTF-8" %><?xml version="1.0" encoding="UTF-8" standalone="yes"?>

       之后的内容可随意换行,一般不会出现什么问题。

 

       (3)为导出的word文件命名

        如果不为word命名,则导出的word文件会自动命名为你所访问的servlet的名称或其他名称。如果想自定义名称可在jsp中加入如下代码实现:

Java代码 复制代码
  1. response.setHeader("Content-disposition","attachment; filename="  
  2.         +new String("文件名称.doc".getBytes("gbk"),    
  3.                 "ISO8859-1" ) +"");  
response.setHeader("Content-disposition","attachment; filename="
		+new String("文件名称.doc".getBytes("gbk"), 
				"ISO8859-1" ) +"");

        具体的编码可根据自己系统的编码进行修改,如果不转码名称中的中文一般都会出现乱码问题。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics