最近在处理 word 文档导出工作,整理并总结下。
经过一番百度和亲测,大部分人使用的都是iText,iReport等...当我去尝试用这几种方法的时候,要实现我的需求可以,但是代码量太大了~~~因为我的 word 文档结构比较复杂,内容较多,有点懒得去写。于是我寻求通过jsp 或 javascript 页面的方式导出,这样子格式都直接在web页面上已经编辑好了,不许通过代码再转成word的形式。
javascript 方式的话需要使用到ActiveXObject,这样子对浏览器是有要求的~~直接放弃
通过jsp方式的话,技术难点关键在图片的导出。百度可以知道,把图片转为base64编码直接输出至页面即可,后面就一直往这个方向走,最后结合FreeMarker,实现了需求。
下面给出步骤
建立 word 文档模板
word 文档另存为 xml 格式
在这一步,我尝试直接把xml文件放到后台,把图片base64编码通过el表达式直接替换,发现导出word文档打开会发生错误,因此,我再绕一下,把它另存为.ftl freeMarker模板
3. 编辑xml,把变量替换,改为el表达式,如这里把某图片改为el表达式
<pkg:part pkg:name="/word/media/image4.jpeg" pkg:contentType="image/jpeg" pkg:compression="store">
<pkg:binaryData>${dataPic}</pkg:binaryData>
</pkg:part>4. 把模板放到项目下,我这里以 /WEB-INF/templates
因为我结合了spring mvc 去实现,功能,因此我在 applicationContext.xml 中做好freeMarkerConfig配置如:
<!-- Freemarker 配置 --> <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> <property name="templateLoaderPath" value="/WEB-INF/templates/" /> <property name="defaultEncoding" value="UTF-8" /> <property name="freemarkerSettings"> <props> <prop key="template_update_delay">10</prop> <prop key="locale">zh_CN</prop> <prop key="number_format">0.##########</prop> <prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop> <prop key="classic_compatible">true</prop> <prop key="template_exception_handler">ignore</prop> </props> </property> </bean>
5. 添加解析 freeMarker 的 ViewResolver
<bean id="ftlViewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" /> <property name="suffix" value=".ftl" /> <property name="exposeRequestAttributes" value="true" /> <property name="exposeSessionAttributes" value="true" /> <property name="exposeSpringMacroHelpers" value="true" /> <property name="order" value="0" /> </bean>
6. 编写 controller
@RequestMapping(value = "/report")
public String word(Model model) {
getResponse().setCharacterEncoding("UTF-8");
getResponse().setContentType("application/msword");
getResponse().addHeader("Content-Disposition", "attachment;filename=report.doc");
// JFreeChart 图片
model.addAttribute("dataPic", Base64Utils.image2Str(ChartUtils.createLineChart(prepareDataset(), "最近7天血压数据", "时间", "mmHg"), 1200, 800));
return "report";
}这里还提供一下图片转base64的一个工具类
public class Base64Utils {
private static BASE64Encoder encoder = new BASE64Encoder();
private Base64Utils() {
}
/**
* 本地图片转 base64 编码输出
*/
public static String localImage2Str(String imagePath) {
File imageFile = new File(imagePath);
if (imageFile.exists() && imageFile.isFile()) {
try {
return image2Str(new FileInputStream(imageFile));
} catch (FileNotFoundException e) {
// ignore
}
}
return "";
}
/**
* JFreeChart 图表转 base64 编码
*/
public static String chartImage2Str(JFreeChart chart, int width, int height) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
ChartUtilities.writeChartAsJPEG(out, 1.0f, chart, width, height, null);
out.flush();
byte[] data = out.toByteArray();
return image2Str(new ByteArrayInputStream(data));
} catch (IOException e) {
// ignore
} finally {
try {
out.close();
} catch (IOException e) {
// ignore
}
}
return "";
}
/**
* 网络图片转 base64 编码输出
*/
public static String webImage2Str(String urlPath) {
InputStream in = null;
try {
URL url = new URL(urlPath);
URLConnection connection = url.openConnection();
connection.connect();
in = connection.getInputStream();
return image2Str(in);
} catch (IOException e) {
// ignore
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// ignore
}
}
}
return "";
}
/**
* 图片输入流转 base 64 编码
*/
public static String image2Str(InputStream stream) {
if (stream != null) {
try {
byte[] data = new byte[stream.available()];
int length = stream.read(data);
if (length > 0) {
return encoder.encode(data);
}
} catch (IOException e) {
// ignore
}
}
return "";
}
}本文出自 “半桶水” 博客,请务必保留此出处http://kinken.blog.51cto.com/4569049/1709913
原文:http://kinken.blog.51cto.com/4569049/1709913