最近项目相关功能中需要导出word文件,不过之前已经有同事完成了相关功能。他的实现方式如下:
将已准备好的word模板另存为html格式,然后将导出后的html格式化后直接拷贝到jsp,并在jsp开始位置加入
<%@page contentType="application/msword; charset=UTF-8" %>
。之后,使用系统数据替换jsp中对应的内容即可。
导出时,只需要将导出动作指向到该jsp页面,即可自动下载为word格式的文件。
经测试,通过以上方式导出word,打开文件后会提示某些文件丢失,导致word格式不完整,且打开后默认显示为html样式的问题。问题很诡异,因为之前同时做的时候没有发现这样的情况,而现在发现后也没有找到解决办法。-_-!!无奈就放弃了这个做法(项目时间原因。。。大家可以参考此方法,完全可行,就是不知道我们的问题出在哪。。。)。
word导出
下面是目前项目使用的导出方法,这个方法与上面的方法类似,是将wrod以xml格式进行处理,实现方式如下:
1.文本内容导出
将已准备好的word模板另存为xml格式(可选择2003xml格式,提高兼容性),然后将导出的xml格式化后直接拷贝到jsp,并在jsp开始位置加入
<%@page contentType="application/msword; charset=UTF-8" %>
,导出方式与html格式的一样。 xml格式的内容看起来更规范,也方便进行循环等数据操作。(关键是使用此方法后,word导出格式完全正常了^_^)
注:xml格式的word文件中首行内容
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
必须保证在jsp文件的第一行,否则导出的word将无法打开,提示格式错误。
2.图片导出到word
貌似这方面的资料比较少,查了很多资料才找到的-_-!!,实现方式如下:
将一个包含图片的word文件另存为xml格式,然后打开xml文件,可找到类似代码如下
<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>
注意
<w:binData w:name="wordml://02000001.jpg" xml:space="preserve">
...
...
</w:binData>
之间的内容,此标签所包含的内容便是我们要插入图片的Base64编码,我们需要做的就是将需要导出的图片转换为base64编码,然后将编码嵌入到对应的标签内即可。
实例代码(由于xml的内容太多,所以这里只给出主要内容,其他省略)
<%@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>
/**
* 获取图片的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)导出时抛出如下异常:
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 version="1.0" encoding="UTF-8" standalone="yes"?>
必须放在jsp文件的第一行。如果此代码前还需要放其他内容,将所有内容放都放在第一行,不换行就可以了。例如
<%@page contentType="application/msword; charset=UTF-8" %><?xml version="1.0" encoding="UTF-8" standalone="yes"?>
之后的内容可随意换行,一般不会出现什么问题。
(3)为导出的word文件命名
如果不为word命名,则导出的word文件会自动命名为你所访问的servlet的名称或其他名称。如果想自定义名称可在jsp中加入如下代码实现:
response.setHeader("Content-disposition","attachment; filename="
+new String("文件名称.doc".getBytes("gbk"),
"ISO8859-1" ) +"");
具体的编码可根据自己系统的编码进行修改,如果不转码名称中的中文一般都会出现乱码问题。
分享到:
相关推荐
java导出word使用freemarker模板map数据导出word带图片 可以循环map 中list。 调用的2种方法在博客 https://blog.csdn.net/yjflinchong/article/details/122614203
windows下,使用python 将Excel中数据批量导出到Word模板中生成新的文件
网络上的根据模板填充Word我都看过一些, 它们的功能在数据换行的时候用的是run对象的.addCarriageReturn()方法,或者是直接用\n实现换行。这些都不符合我的需求, 因为我要的是分段,而不是换行。换行的word导致另一...
根据word模板导出word、...本资源中集成了 根据word模板导出word功能 、合并多个word功能 、word转换成pdf功能 、文件删除功能能。 其中坐标以$开头为一对一查询结果替换 $t为表格模板开头标识 $p为图片模板开头标识
pdm导出word模板(附使用说明)
使用C# NET Core技术,通过预设的html模板,导出Word文件,Html文件,Pdf,使用说明参考https://blog.csdn.net/qq_27337291/article/details/120676751?spm=1001.2014.3001.5501
PowerDesigner导出Word模板文件
自定义导出word模板,模板包含表清单、索引清单、表列清单
一个使用Apache的poi使用word模板循环输出表格行并导出的例子
Power Designer导出word模板下载,Power Designer导出数据结构模板下载
就可以通过现有信息导出Word文档。基于Java语言来导出Word文档的方式也有很多种,如Jacob,Apache POI,Freemarker,PageOffice,java2word 等等。。。。 在这里将通过Freemarker这个模板引擎来实现导出 Word,项目...
java使用word模板导出个人简历 a、处理word2003模板导出doc文件 b、处理word2007模板导出docx文件
最近因项目开发的需要,整理了一份用JAVA导出WORD文档,其部署步骤如下: 1、将jacob-1.14.3-x86.dll放在服务器的系统盘(或运行本机的系统):\WINDOWS\system32目录下。 2、将jacob-1.14.3-x86.dll放在JDK 的 bin ...
c#导出word文件,附带word纸张页边距,字体,行边距,间距紧缩比 磅值等的设置。使用的时候需要引用dll
支持php、thinkphp进行将html页面直接导出为word,样式可一并导出为word
freemarker+itext5实现用模板方式,导出word和pdf 的模板示例文件,使用已经简单编写的word,生成的xml文件和html.
java freemarker导出word -包含多张图片导出
导出WORD,C#模板导出word,定制开发,源码技术
利用poi读取word模板文件,并回填逻辑数据,生成并导出需要的word文档源码。解决模板读取异常问题,提供wordUtils工具类(各种功能实现)