如何从HCL Domino XPage程序化生成PDF并作为邮件附件发送?
从XPage程序化生成PDF并作为邮件附件发送的实现方案
核心逻辑
直接复用现有XPage的渲染能力,先将XPage转换为HTML字符串,再把HTML转成符合A4规格的PDF,最后通过Domino API发送带该PDF附件的邮件,完全避免维护重复页面。
具体步骤与代码示例
1. 服务器端渲染XPage为HTML字符串
在XPage的服务器端按钮或Java代理中,利用Domino的上下文对象渲染目标XPage,得到包含用户填写字段值的完整HTML内容:
import com.ibm.xsp.domino.context.DominoContext; import com.ibm.xsp.webapp.XspHttpServletResponse; import javax.servlet.http.HttpServletRequest; import java.io.StringWriter; // 获取当前Domino上下文 DominoContext dc = DominoContext.getCurrentUnchecked(); HttpServletRequest request = dc.getRequest(); XspHttpServletResponse response = (XspHttpServletResponse) dc.getResponse(); // 渲染指定XPage为HTML字符串(替换成你的培训表XPage路径) StringWriter htmlWriter = new StringWriter(); dc.renderPage("/UserTrainingForm.xsp", request, response, htmlWriter); String xpageHtmlContent = htmlWriter.toString();
注意:可通过URL参数(如
/UserTrainingForm.xsp?pdfMode=true)在XPage中隐藏不需要的元素(比如提交按钮、导航栏),确保PDF内容和用户填写的表单完全一致。
2. 将HTML转换为A4格式的PDF
使用Domino自带的Apache FOP库完成HTML到PDF的转换,需先准备一个XSL样式表(html2fo.xsl),将HTML结构映射为符合A4规格的XSL-FO格式:
import org.apache.fop.apps.Fop; import org.apache.fop.apps.FopFactory; import org.apache.fop.apps.MimeConstants; import org.w3c.dom.Document; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.sax.SAXResult; import javax.xml.transform.stream.StreamSource; import java.io.ByteArrayOutputStream; import java.io.StringReader; import org.cyberneko.html.parsers.DOMParser; import org.xml.sax.InputSource; // 用NekoHTML解析HTML为DOM文档 DOMParser htmlParser = new DOMParser(); htmlParser.parse(new InputSource(new StringReader(xpageHtmlContent))); Document htmlDom = htmlParser.getDocument(); // 加载HTML转XSL-FO的样式表(需自定义适配你的表单样式) StreamSource xslStyle = new StreamSource(getClass().getResourceAsStream("/html2fo.xsl")); Transformer transformer = TransformerFactory.newInstance().newTransformer(xslStyle); // 生成A4规格的PDF字节数组 FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI()); ByteArrayOutputStream pdfOutput = new ByteArrayOutputStream(); Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, pdfOutput); transformer.transform(new DOMSource(htmlDom), new SAXResult(fop.getDefaultHandler())); byte[] pdfBytes = pdfOutput.toByteArray();
自定义
html2fo.xsl时,要在FO中指定页面规格:<fo:page-master master-name="A4">,并设置page-height="297mm" page-width="210mm"。
3. 发送带PDF附件的邮件
通过Domino的Notes API创建邮件文档,嵌入生成的PDF作为附件:
import lotus.domino.*; // 获取当前Domino会话与数据库 Session dominoSession = NotesFactory.createSession(); Database currentDb = dominoSession.getCurrentDatabase(); // 创建邮件文档 Document mailDoc = currentDb.createDocument(); mailDoc.replaceItemValue("Form", "Memo"); mailDoc.replaceItemValue("SendTo", "target@example.com"); // 替换为收件人邮箱 mailDoc.replaceItemValue("Subject", "用户培训表PDF"); mailDoc.replaceItemValue("Body", "您好,附件为您填写的用户培训表PDF版本。"); // 嵌入PDF附件 RichTextItem bodyRt = mailDoc.createRichTextItem("Body"); bodyRt.embedObject(EmbeddedObject.EMBED_ATTACHMENT, "", "用户培训表.pdf", pdfBytes); // 发送邮件 mailDoc.send();
关键注意事项
- 确保XPage的CSS样式在PDF中正常生效,优先使用内联样式或在XSL-FO中统一定义字体、间距等样式。
- 若用户点击按钮触发操作,需先保存文档再执行PDF生成逻辑,保证HTML内容包含最新的用户输入。
- 高并发场景下建议将PDF生成与邮件发送逻辑放到后台代理中异步执行,避免阻塞前端页面。
内容的提问来源于stack exchange,提问作者Michał
相关产品推荐
相关产品推荐

