转载请注明出处即可:https://blog.csdn.net/qq_35431789/article/details/114258862
接口几乎已经兼容了所有主流的浏览器。
这个功能还是我接手的别人写的未成品基础上写的……顺便吐槽下ftl模板文件是真的麻烦!
使用freemarker模板生成doc与pdf文件。一般使用freemarker模板生成doc与pdf文件的功能是因为系统中有需要固定生成的文档格式需求,本篇基本能解决这类需求。大家可以通过这篇博文进行学习和参考。
模板的上传功能就不写了,因为大家的文件存储方式和位置都不同,只写如何生成doc和pdf的功能。
以下是代码内容:
1、controller:
/**
* 下载
*
* @param
* @param id 是模板的ID
* @param snumber 是要定义的文件名称
* @param type 判断是下载什么模板,这里自定义
* @param downloadtype 下载的文件类型
* @throws IOException
* @return
* 具体的传参请根据需求修改
*/
@RequestMapping(value = "download")
@ResponseBody
public JSONObject exportToWord(HttpServletResponse response, HttpServletRequest request,
@RequestParam("id") String id,
@RequestParam("snumber") String snumber,
@RequestParam("downloadtype") String downloadtype,
@RequestParam("type") String type) throws Exception {
//map用来存放需要插入文件的内容
Map<String, Object> map = new HashMap<>();
InputStream input = null;
OutputStream outs = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
//这里定义实体list的数据对象,根据自己的需求请灵活使用
List<ExportContract> list = new ArrayList<ExportContract>();
JSONObject jsonobj = new JSONObject();
//使用临时文件
File file = File.createTempFile(snumber,".doc");
log.info("临时文件所在的本地路径:" + file.getCanonicalPath());
String PDFfileName =null;
try {
if(Integer.parseInt((type)) ==0 ){//判断是下载什么模板
//获取插入模板的数据
list = server.findAlldataByOrderId(snumber);
}else if(Integer.parseInt((type)) ==2 ){
//获取插入模板的数据
list = server.findAlldataByOrder(snumber);
}
if (list == null || list.size() <= 0) {
jsonobj.put("success", false);
jsonobj.put("msg", "获取数据失败!");
return jsonobj;
}
ExportContract ext = list.get(0);
//账户名称
map.put("sname ", ext.getSname());
//list遍历表格数据,根据freemarker规范定义,表格内的数据需要单独存放
List<Map> prolist = new ArrayList<Map>();
for (int i = 0; i < list.size(); i++) {
Map<String, Object> mapdetail = new HashMap<String, Object>();
ExportContract extdtl = list.get(i);
//数量
mapdetail.put("qty", extdtl.getQty());
prolist.add(mapdetail);
}
map.put("prolist", prolist);
//读取ftl文件
Configuration conf = new Configuration(new Version("2.3.0"));
conf.setDefaultEncoding("UTF-8");
//模板文件的读取方式有三种,请根据使用场景自行查询,这里只写本地存放ftl文件
conf.setDirectoryForTemplateLoading(new File("/contract_template"));
Template tem=null;
//输出文档路径及名称
String downFileName = null;
//utf-8读取模板ftl文件
String filename = server.findByUrls(id);
//先获取rul,在截取文件名
String name = filename;
//Template tem = conf.getTemplate(name, "utf-8");
try {
tem = conf.getTemplate(name);
} catch (Exception e) {
e.printStackTrace();
}
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "utf-8"), 10240);
tem.process(map, out);
out.close();
// 设置强制下载不打开
if(downloadtype.equals("PDF")){
//word文档转pdf文档
PDFfileName = word2Pdf(file.getCanonicalPath(), null);
log.info("PDF文件临时地址:"+PDFfileName);
if(Integer.parseInt((type)) ==0 ){
downFileName = ext.getSname() + snumber + ".pdf";
}else if(Integer.parseInt((type)) ==2 ){
downFileName = ext.getSname() + snumber + ".pdf";
}
bis = new BufferedInputStream(new FileInputStream(PDFfileName));
}else{
if(Integer.parseInt((type)) ==0 ){
downFileName = ext.getSname() + snumber + ".doc";
}else if(Integer.parseInt((type)) ==2 ){
downFileName = ext.getSname() + snumber + ".doc";
}
bis = new BufferedInputStream(new FileInputStream(file));
}
response.setCharacterEncoding("UTF-8");
response.addHeader("Content-Disposition", "attachment;fileName=" + downFileName);
response.setContentType("application/octet-stream;charset=utf-8");
final String agent = request.getHeader("User-Agent");
String attachment = "attachment;fileName=";
filename = downFileName;
outs = response.getOutputStream();
bos = new BufferedOutputStream(outs);
String outputFilename = null;
if (agent.indexOf("Firefox") > 0) {
attachment = "attachment;fileName*=";
outputFilename = "=?UTF-8?B?"
+ (new String(Base64.encodeBase64(filename
.getBytes("UTF-8")))) + "?=";
} else {
if (agent.indexOf("MSIE") != -1) {
outputFilename = new String(filename.getBytes("gbk"), "iso8859-1");
} else {
outputFilename = new String(filename.getBytes("UTF-8"), "iso8859-1");
}
}
response.setHeader("Content-Disposition", attachment + outputFilename);
int bytesRead = 0;
// 输入流进行先读,然后用输出流去写,下面用的是缓冲输入输出流
byte[] buffer = new byte[512];
while ((bytesRead = bis.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
}
bos.flush();
log.info("文件下载成功!!!!!");
jsonobj.put("success", true);
return jsonobj;
} catch (Exception e) {
e.printStackTrace();
log.info("文件下载失败!!!!!");
jsonobj.put("success", false);
jsonobj.put("msg", "获取数据失败!");
return jsonobj;
} finally {
if (input != null) input.close();
if (outs != null) outs.close();
if (bos !=null) bos.close();
if (bis !=null) bis.close();
//下载完成删除临时文件
boolean flag = false;
boolean flagPDF = false;
flag = file.getAbsoluteFile().delete();//这里有点小bug,懒得改了,使用时遇到请自己解决
File filePDF = new File(PDFfileName);
flagPDF = filePDF.getAbsoluteFile().delete();
log.info("临时WORD文件是否删除成功:" + flag);
log.info("临时PDF文件是否删除成功:" + flagPDF);
}
}
2、Xml2Word2Pdf转换工具类,这个工具类是我网上找到能很好解决转换问题的。使用的aspose.words包。如果部署到Linux服务器,出现乱码,看看是不是字体库没有安装。遇到了不能正确实现的问题请自行探索。
/**
* @Content: xml->word->pdf (通过freemarker把通过word生成的xml模板动态添加数据并生成word文档,通过aspose.words把word文档转为pdf文档)
* @Description: aspose.words需付费购买,目前使用破解版,需要引入freemarker的jar和aspose-words-jdk16-15.8.0.jar
*/
public class Xml2Word2Pdf {
private static Configuration configuration = null;
/**
* 初始化配置并设置默认编码UTF-8
*/
static {
configuration = new Configuration();
configuration.setDefaultEncoding("UTF-8");
}
/**
* @Description: 验证aspose.word组件是否授权:无授权的文件有水印标记
*/
public static boolean getLicense() {
boolean result = false;
try {
String s = "<License><Data><Products><Product>Aspose.Total for Java</Product><Product>Aspose.Words for Java</Product></Products><EditionType>Enterprise</EditionType><SubscriptionExpiry>20991231</SubscriptionExpiry><LicenseExpiry>20991231</LicenseExpiry><SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber></Data><Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature></License>";
ByteArrayInputStream inputStream = new ByteArrayInputStream(s.getBytes());
//InputStream inputStream = Xml2Word2Pdf.class.getClassLoader().getResourceAsStream("\\license.xml");
com.aspose.words.License license = new com.aspose.words.License();
license.setLicense(inputStream);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 使用aspose.word把word文档转为pdf文档
*
* @param sourceFile word文档绝对路径(如:D:/templates/order.doc)
* @param destFile pdf文档绝对路径(如:D:/templates/order.pdf)
*/
public static String word2Pdf(String sourceFile, String destFile) throws Exception {
destFile = StringUtils.isEmpty(destFile) ? sourceFile.replace(".doc", ".pdf") : destFile;
// 验证License 若不验证则转化出的pdf文档会有水印产生
if (!getLicense()) {
throw new Exception("生成PDF文档,验证License失败!");
}
try {
File file = new File(destFile); //新建一个空白pdf文档
FileOutputStream os = new FileOutputStream(file);
//解决Linux中文支持问题,注意,如果部署到新服务器,需要copy window下的字体到Linux服务器字体文件夹中。
String osName = System.getProperties().getProperty("os.name");
if (osName.equals("Linux")) {
FontSettings.setFontsFolder("/usr/share/fonts" + File.separator, true);
}
Document doc = new Document(sourceFile);//通过sourceFile创建word文档对象
doc.save(os, SaveFormat.PDF);
os.close();
} catch (Exception e) {
e.printStackTrace();
throw new Exception("生成PDF文档失败!");
}
return destFile;
}
}
到此,基本实现了这个功能。