网上已经有比较多的例子,但是很多都是简单的 demo,而且有很多隐藏的问题,本人再次写一个完整的demo:
Spring MVC部分:
response.reset();
response.setContentType("application/pdf;charset=utf-8");
fileName = encodeFilename(request, fileName);
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".pdf");
OutputStream rtnos = response.getOutputStream();
String htmlStr = HtmlGenerator.generate("sample.ftl", resultMap);
String imgWidth = "width=\"450\"";
String imgHeight = "height=\"300\"";
htmlStr = htmlStr.replaceAll("width=\"(.*?)\"", imgWidth).replaceAll("height=\"(.*?)\"", imgHeight);
logger.debug("===htmlStr===" + StringEscapeUtils.unescapeHtml(htmlStr));
PdfGenerator.generate(StringEscapeUtils.unescapeHtml(htmlStr).replaceAll("&", "&"), rtnos);
return null;
通过Freemarker模板生成html:
import java.io.BufferedWriter;
import java.io.StringWriter;
import java.util.Map;
import freemarker.template.Configuration;
import freemarker.template.Template;
public class HtmlGenerator {
/**
* Generate html string.
*
* @param template the name of freemarker teamlate.
* @param variables the data of teamlate.
* @return htmlStr
* @throws Exception
*/
public static String generate(String template, Map<String,Object> variables) throws Exception{
Configuration config = FreemarkerConfiguration.getConfiguation();
config.setDefaultEncoding("UTF-8");
Template tp = config.getTemplate(template);
StringWriter stringWriter = new StringWriter();
BufferedWriter writer = new BufferedWriter(stringWriter);
tp.setEncoding("UTF-8");
tp.process(variables, writer);
String htmlStr = stringWriter.toString();
writer.flush();
writer.close();
return htmlStr;
}
}
html转PDF:
import java.io.ByteArrayInputStream;
import java.io.OutputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.xhtmlrenderer.pdf.ITextRenderer;
public class PdfGenerator {
/**
* Output a pdf to the specified outputstream
*
* @param htmlStr the htmlstr
* @param out the specified outputstream
* @throws Exception
*/
public static void generate(String htmlStr, OutputStream out) throws Exception {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(new ByteArrayInputStream(htmlStr.getBytes()));
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(doc, null);
renderer.layout();
renderer.createPDF(out);
out.flush();
out.close();
}
}
sample.ftl(片段):
<#list data as note>
<li data-id="12" data-nodetime="${(note.nodeTime)!}" data-totaltime="${(note.totalTime)!}" data-nodename="${(note.nodeName)!}" data-imgs="${(note.imgsStr)!}" data-content="${(note.content)!}">
<div class="p-notelist-cite-wrap">
<<#if note.reference == "video">a<#else>span</#if> class="p-notelist-cite" href="${(note.subjectUrl)!}">
引用<i <#if note.reference == "video">class="i-icon i-icon-paly "<#else>class="i-icon i-icon-note "</#if>></i>${(note.nodeName)!}
<span class="p-time"> ${(note.nodeTime)!}/${(note.totalTime)!} </span> <#if note.reference == "video"><b>提纲</b></#if>
</<#if note.reference == "video">a<#else>span</#if>>
<div class="p-cite-content">
<div class="p-cite-content-wrap">
<div class="i-subject-content">
<div class="subject subject-choice">
<div class="stem">
<span class="type">[单选]</span>
<span class="use-number"></span>
<p>A是老王</p><img src="http://kaoshi.neibu.koolearn.com/upload/image/1430791311563.png"></img>
<p>B是老张</p>
<p>谁是凶手</p>
</div>
<div class="answer">
<ul>
<li>
<span data-id="0" class="number">A</span>
<span class="content">A是凶手</span>
</li>
<li>
<span data-id="1" class="number">B</span>
<span class="content">B是凶手</span>
</li>
</ul>
</div>
</div>
</div>
</div>
<a href="/project/teach/1.x/demo/apply/searchResult.html" target="_blank" class="p-view"><i class="i-icon i-icon-edit-hover"></i>在做题记录中查看</a>
</div>
</div>
<div class="p-note-content">
<span>${(note.content)!}</span>
<#if note.imgs??>
<#list note.imgs as img>
<img src="${(img)!}" alt=""></img>
</#list>
</#if>
</div>
<div class="p-note-bottom">
<i class="i-icon i-icon-notemark"></i><span class="p-note-mark">${(note.mark)!}</span>
<div class="p-note-operate">
<span>${(note.time)!}</span>
</div>
</div>
</li>
</#list>