Oracle APEX中如何为生成的PDF附加XML文件?
在Oracle APEX中为PDF附加XML附件的实现方案
方法1:Java存储过程 + iText(推荐)
iText是成熟的PDF处理库,通过Java存储过程集成到Oracle数据库后,能轻松实现PDF附件添加:
- 部署iText库:将iText的jar包(如
itextpdf-5.5.13.jar)加载到Oracle数据库中(需DBA权限,使用loadjava命令)。 - 创建Java处理类:
import com.itextpdf.text.pdf.PdfReader; import com.itextpdf.text.pdf.PdfStamper; import com.itextpdf.text.pdf.PdfFileSpecification; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; public class PdfAttacher { public static byte[] attachXml(byte[] pdfData, byte[] xmlData, String xmlFileName) throws Exception { PdfReader reader = new PdfReader(new ByteArrayInputStream(pdfData)); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); PdfStamper stamper = new PdfStamper(reader, outputStream); // 嵌入XML附件 PdfFileSpecification attachment = PdfFileSpecification.fileEmbedded( stamper.getWriter(), null, xmlFileName, xmlData ); stamper.addFileAttachment(attachment); stamper.close(); reader.close(); return outputStream.toByteArray(); } }
- 创建PL/SQL包装函数:
CREATE OR REPLACE FUNCTION ATTACH_XML_TO_PDF( p_pdf_blob IN BLOB, p_xml_blob IN BLOB, p_xml_filename IN VARCHAR2 ) RETURN BLOB IS LANGUAGE JAVA NAME 'PdfAttacher.attachXml(byte[], byte[], java.lang.String) return byte[]'; /
- 在APEX中调用:
- 先获取生成好的PDF BLOB(比如通过
APEX_PDF生成,或从表中读取)。 - 获取要附加的XML BLOB(可通过
APEX_DATA_EXPORT生成,或从XMLType转换)。 - 调用函数得到带附件的PDF,再通过
APEX_UTIL.DOWNLOAD_BLOB提供下载:DECLARE l_pdf BLOB; l_xml BLOB; l_final_pdf BLOB; BEGIN -- 假设从表中读取PDF和XML SELECT pdf_content INTO l_pdf FROM pdf_table WHERE id = 1; SELECT xml_content INTO l_xml FROM xml_table WHERE id = 1; l_final_pdf := ATTACH_XML_TO_PDF(l_pdf, l_xml, 'data.xml'); -- 输出给用户下载 APEX_UTIL.DOWNLOAD_BLOB( p_content_type => 'application/pdf', p_blob => l_final_pdf, p_filename => 'document_with_attachment.pdf' ); END;
- 先获取生成好的PDF BLOB(比如通过
方法2:命令行工具 + APEX外部进程
如果服务器允许执行外部命令,可使用开源工具pdftk(PDF Toolkit):
- 安装pdftk:在APEX应用服务器上安装pdftk。
- 配置数据库权限:
- 创建
UTL_FILE可用的临时目录,授予读写权限。 - 确保
DBMS_SCHEDULER能执行外部命令。
- 创建
- PL/SQL调用逻辑:
DECLARE l_temp_pdf_dir VARCHAR2(100) := 'TEMP_PDF_DIR'; l_temp_pdf_path VARCHAR2(200) := 'temp.pdf'; l_temp_xml_path VARCHAR2(200) := 'attachment.xml'; l_output_path VARCHAR2(200) := 'final.pdf'; l_final_pdf BLOB; BEGIN -- 将PDF和XML写入临时文件 UTL_FILE.PUT_RAW(UTL_FILE.FOPEN(l_temp_pdf_dir, l_temp_pdf_path, 'WB'), p_pdf_blob); UTL_FILE.PUT_RAW(UTL_FILE.FOPEN(l_temp_pdf_dir, l_temp_xml_path, 'WB'), p_xml_blob); -- 调用pdftk添加附件 DBMS_SCHEDULER.CREATE_JOB( job_name => 'ADD_PDF_ATTACH_JOB', job_type => 'EXECUTABLE', job_action => '/usr/bin/pdftk', arguments => l_temp_pdf_path || ' attach_files ' || l_temp_xml_path || ' output ' || l_output_path, job_class => 'DEFAULT_JOB_CLASS', enabled => TRUE, auto_drop => TRUE ); -- 等待任务完成后读取结果BLOB(需添加等待逻辑或异步处理) -- 示例读取逻辑 l_final_pdf := UTL_FILE.GET_BLOB(l_temp_pdf_dir, l_output_path); -- 输出下载 APEX_UTIL.DOWNLOAD_BLOB( p_content_type => 'application/pdf', p_blob => l_final_pdf, p_filename => 'document_with_xml.pdf' ); END;
可用工具选项
- iText:功能全面,支持复杂PDF操作,适合集成到数据库内部处理,无外部依赖(除了jar包)。
- pdftk:轻量命令行工具,语法简单,适合快速实现,但需要服务器权限支持。
- PL_PDF:纯PL/SQL的PDF处理包,无需Java环境,直接在Oracle中使用,需自行下载安装。
内容的提问来源于stack exchange,提问作者Rana mari
相关产品推荐
相关产品推荐

