欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Springboot 使用freemaker导出word文档

程序员文章站 2022-12-07 19:30:01
利用freemarker导出word文档,主要分为一下几部分,但是循环写入图片是其中最难的一点,尤其是从未使用freemaker导出word模板的新手。话不多说,开搞。1 找到需要导出的word模板,我的模板截图如下,其中涉及到了表格,文字以及图片(模板中只放了一张图片,事实是不固定数量的)2 将word文档另存为xml文件,这里建议使用office来操作,wps没有实践过,网上都是推荐使用office来制作模板,具体有兴趣的可以单独实践。另存为xml文件以后,使用其他工具打开xml文件.....
利用freemarker导出word文档,主要分为一下几部分,但是循环写入图片是其中最难的一点,尤其是从未使用freemaker导出word模板的新手。话不多说,开搞。
1  找到需要导出的word模板,我的模板截图如下,其中涉及到了表格,文字以及图片(模板中只放了一张图片,事实是不固定数量的)
Springboot 使用freemaker导出word文档
2 将word文档另存为xml文件,这里建议使用office来操作,wps没有实践过,网上都是推荐使用office来制作模板,具体有兴趣的可以单独实践。另存为xml文件以后,使用其他工具打开xml文件,并格式化格式。其中将需要实时填充的地方用参数代替,比如我下图中 朝鲜战争需要实时传入,则用${title}代替,模板中的所有文字参数地方都可以使用此方法,然后将.xml后缀修改为.ftl,并将ftl文件放在项目指定位置。
Springboot 使用freemaker导出word文档Springboot 使用freemaker导出word文档
3 模板中含有图片以及图片数量不固定的情况,则需要以下步骤,
3.1  在模板中 <w:body></w:body>标签中 把事先放入占位的图片换为循环展示 的id要和一致  入下图。
Springboot 使用freemaker导出word文档
3.2 在 <pkg:xmlData>中定义图片id Relationships中循环定义图片id (注意图片id不能重复,重复会导致写入的图片无法显示)
Springboot 使用freemaker导出word文档
3.3 找到事先放入的图片的字节流位置( pkg:binaryData中一大段字符串),替换为循环的base64,如上图中。其中需要将图片 转换成BASE64字符串,具体方法百度,很多工具类。
注意,以上三个地方图片id必须保持一致否则可能出现填充的图片无法显示的情况。
4 如果文字需要循环填充,则使用下图中的list循环填充即可,if是判断此参数是否存在的,一般来说添加不会出错,不添加则需要保证传入的参数一定要有此参数名称,否则报错
Springboot 使用freemaker导出word文档
5 编写代码,将需要填充的参数放入一个map中,使用工具类即可生成报告。

6 工具类如下:

import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.zip.ZipOutputStream;

/**
 * 导出
 * @author
 * @date
 */
@Component
public class ExportUtil {

	private static Logger logger = LoggerFactory.getLogger(ExportUtil.class);

	@Autowired
	private Configuration freemarkerConfig;

	/**
	 * 通过浏览器导出excel
	 * 
	 * @param response
	 * @param freemarkerTemplateName
	 * @param map
	 */
	public void exportExcel(HttpServletResponse response, String freemarkerTemplateName, String excelName, HashMap<String, Object> map) {
		Writer out = null;
		try {
			excelName = excelName.replaceAll(" ", "_");
			response.reset(); // 清空输出流
			response.setContentType("application/msexcel;charset=utf-8");
			response.setHeader("Content-disposition", "attachment; filename=" + excelName + ".xls");// 设定输出文件头
			out = response.getWriter();
			Template template = freemarkerConfig.getTemplate(freemarkerTemplateName);
			template.setEncoding("utf-8");
			template.process(map, out);
			
			if (out != null) {
				out.flush();
				out.close();
			}
		} catch (Exception e) {
			logger.error("导出excel失败", e);
			if (out != null) {
				try {
					out.close();
				} catch (IOException ignore) {
				}
			}
		}
	}

	/**
	 * 通过浏览器导出word
	 * 
	 * @param response
	 * @param freemarkerTemplateName
	 * @param map
	 */
	public void exportWord(HttpServletResponse response, String freemarkerTemplateName, String wordName, HashMap<String, Object> map) {
		Writer out = null;
		try {
			response.reset();// 清空输出流
			response.setContentType("application/msword;charset=utf-8");
			response.setHeader("Content-disposition", "attachment; filename=" + wordName + ".doc");// 设定输出文件头
			out = response.getWriter();
			Template template = freemarkerConfig.getTemplate(freemarkerTemplateName);
			template.setEncoding("utf-8");
			template.process(map, out);
			if (out != null) {
				out.flush();
				out.close();
			}
		} catch (Exception e) {
			logger.error("导出word失败", e);
			if (out != null) {
				try {
					out.close();
				} catch (IOException e1) {
					logger.error("导出word失败", e1);
				}
			}
		}
	}

	/**
	 * 导出到指定目录
	 * @param directory 文件存放的目录
	 * @param freemarkerTemplateName
	 * @param fileName 文件名带文件后缀
	 * @param map
	 */
	public void exportWord(String directory, String freemarkerTemplateName, String fileName, HashMap<String, Object> map) {
		OutputStreamWriter out = null;
		try {
			File dir = new File(directory);
			if(!dir.exists()){
				if(!dir.mkdirs()){
					logger.error("创建目录异常:{}",dir.toString());
					return;
				}
			}
			if(!dir.isDirectory()){
				FileUtils.deleteQuietly(dir);
				logger.error("目录错误");
				return;
			}
			File file = new File(directory+File.separator+fileName);
			out = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8);

			Template template = freemarkerConfig.getTemplate(freemarkerTemplateName);
			template.setEncoding("utf-8");
			template.process(map, out);
			out.flush();
			out.close();
		} catch (Exception e) {
			logger.error("导出word失败", e);
			if (out != null) {
				try {
					out.close();
				} catch (IOException e1) {
					logger.error("导出word失败", e1);
				}
			}
		}
	}

	/**
	 * 导出zip
	 * @param response
	 * @param files
	 * @param path
	 * @param exportName
	 */
	public void exportZip(HttpServletResponse response, List<File> files, String path, String exportName){
		OutputStream out = null;
		String zipPath = path + exportName + ".zip";
		File zipFile = new File(zipPath);
		try{
			FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
			ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream);
			ZipUtil.zip(files, zipOutputStream);
			zipOutputStream.close();
			fileOutputStream.close();
			//删除文件
			files.forEach(
					file -> {
						file.delete();
					}
			);
			response.reset();
			response.setContentType("application/x-zip-compressed;charset=utf-8");
			response.setHeader("Content-disposition", "attachment; filename=" + exportName);
			InputStream in = new FileInputStream(zipFile);
			int len = 0;
			byte[] buffer = new byte[1024];
			out = response.getOutputStream();
			while((len=in.read(buffer))>0){
				out.write(buffer,0,len);
			}
			in.close();
			out.flush();
			out.close();
		}catch (Exception e){
			logger.error("导出zip失败", e);
			if (out != null) {
				try {
					out.close();
				} catch (IOException e1) {
					logger.error("导出zip失败", e1);
				}
			}
		}
		if (zipFile.exists()) {
			zipFile.delete();
		}
	}

	public void exportZipPath(List<File> files, String path, String exportName){
		OutputStream out = null;
		String zipPath = path + exportName + ".zip";
		File zipFile = new File(zipPath);
		try{
			FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
			ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream);
			ZipUtil.zip(files, zipOutputStream);
			zipOutputStream.close();
			fileOutputStream.close();
			//删除文件
			files.forEach(
					file -> {
						file.delete();
					}
			);
		}catch (Exception e){
			logger.error("生成zip失败", e);
			if (out != null) {
				try {
					out.close();
				} catch (IOException e1) {
					logger.error("导出zip失败", e1);
				}
			}
		}
	}

	@SuppressWarnings("unused")
	private String formatTime(Date date, String pattern) {
		if (date == null) {
			return "";
		} else {
			return DateFormatUtils.format(date, pattern);
		}
	}

	/**
	 * 项目名称:pscms_hlj_web_base
	 * 
	 * @param content
	 * @return 描述: 截取字符串,截取到最后一个句号,问号,或者感叹号,总字数不超过1000 创建人:yww 创建时间:2012-7-23
	 *         下午2:32:59 修改人:yww 修改时间:2012-7-23 下午2:32:59 修改备注:
	 * @version
	 */
	private String truncateContent(String content) {
		int limit = 1000;
		String truncatedContent = content;
		if (content.endsWith("......")) {
			List<Integer> posNum = new ArrayList<Integer>();
			posNum.add(truncatedContent.lastIndexOf("。"));
			posNum.add(truncatedContent.lastIndexOf("?"));
			posNum.add(truncatedContent.lastIndexOf("!"));
			posNum.add(truncatedContent.lastIndexOf("?"));
			posNum.add(truncatedContent.lastIndexOf("!"));
			Collections.sort(posNum);
			int finalPos = posNum.get(posNum.size() - 1) + 1; // 因为截取的时候不包含标点符号出现的位置,所以要+1
			if (finalPos != 0 && finalPos <= limit) { // 如果找到,那么截取到当前符号的位置
				truncatedContent = truncatedContent.substring(0, finalPos);
			}
		}
		
		if (content.length() > limit) { // 小与1000时直接返回
			truncatedContent = content.substring(0, limit);
		}
		List<Integer> posNum = new ArrayList<Integer>();
		posNum.add(truncatedContent.lastIndexOf("。"));
		posNum.add(truncatedContent.lastIndexOf("?"));
		posNum.add(truncatedContent.lastIndexOf("!"));
		posNum.add(truncatedContent.lastIndexOf("."));
		posNum.add(truncatedContent.lastIndexOf("?"));
		posNum.add(truncatedContent.lastIndexOf("!"));
		Collections.sort(posNum);
		int finalPos = posNum.get(posNum.size() - 1) + 1; // 因为截取的时候不包含标点符号出现的位置,所以要+1
		if (finalPos != 0 && finalPos <= limit) { // 如果找到,那么截取到当前符号的位置
			truncatedContent = truncatedContent.substring(0, finalPos);
		}
		return truncatedContent;
	}  
}
本文地址:https://blog.csdn.net/juanqiao7497/article/details/110231658
相关标签: freemarker java