Oracle Apex调用REST API返回PDF异常:仅显示填充数据无模板内容
问题概述
我有一个REST API,可接收PDF模板及填充数据,返回已填充数据的PDF文件。该API在Postman中测试正常,但使用Oracle Apex调用时(页面提交时执行如下代码),下载的PDF仅包含填充的数据,模板原有内容丢失。例如模板包含固定文本和表单域,生成的PDF仅显示填充后的表单域,无其他内容。此问题仅在Apex调用时出现。
原代码:
DECLARE lc_response CLOB; l_blob BLOB; lm_multipart apex_web_service.t_multipart_parts; lc_json CLOB := '[{ "D1": 194645, "R1": 1, "R2": 9, "R3": 4, "R4": 6, "R5": 4, "R6": 5 }]'; lv_filename VARCHAR2(20) := 'my_file.pdf'; lv_base_url VARCHAR2(100) := 'http://10.50.200.11:27005/report'; -- webservice base URL; lv_api_key VARCHAR2(100); -- API KEY lb_blob BLOB; -- Blob part of the multipart l_dest_offset PLS_INTEGER := 1; l_src_offset PLS_INTEGER := 1; l_lang_context PLS_INTEGER := dbms_lob.default_lang_ctx; l_warning PLS_INTEGER := dbms_lob.warn_inconvertible_char; l_file_mimetype apex_application_files.mime_type%TYPE; BEGIN -- Select unfilled PDF template stored as BLOB in database SELECT input_template INTO lb_blob FROM python_input_template WHERE sno = 1; apex_web_service.set_request_headers( p_name_01 => 'x-api-key', p_value_01 => 'qwerty_key', p_name_02 => 'x-api-user', p_value_02 => 'APEX' ); /*Supply data to fill the pdf with*/ apex_web_service.append_to_multipart( p_multipart => lm_multipart, p_name => 'data_str', p_content_type => 'application/json', p_body => lc_json ); /*Supply the template to be filled*/ apex_web_service.append_to_multipart( p_multipart => lm_multipart, p_name => 'template', p_filename => lv_filename, p_content_type => 'application/pdf', p_body_blob => lb_blob ); lc_response := apex_web_service.make_rest_request( p_url => lv_base_url, p_http_method => 'POST', p_body_blob => apex_web_service.generate_request_body(lm_multipart) ); /*convert CLOB responce to BLOB*/ dbms_lob.createtemporary( lob_loc => l_blob, cache => true ); dbms_lob.converttoblob( dest_lob => l_blob, src_clob => lc_response, amount => dbms_lob.lobmaxsize, dest_offset => l_dest_offset, src_offset => l_src_offset, blob_csid => dbms_lob.default_csid, lang_context => l_lang_context, warning => l_warning ); sys.htp.init; owa_util.mime_header( 'application/pdf', false, 'UTF-8' ); sys.htp.p('Content-Disposition: attachment; filename="' || 'l_file_name.pdf' || '"'); sys.htp.p('Content-length: ' || sys.dbms_lob.getlength(l_blob)); sys.owa_util.http_header_close; wpg_docload.download_file(l_blob); apex_application.stop_apex_engine; END;
可能的原因及解决方法
1. 二进制响应被错误转为CLOB处理
API返回的是二进制PDF文件,原代码先将其作为CLOB接收,再转BLOB的过程中,二进制数据会被当作文本解析,导致PDF结构损坏,仅保留了可识别的文本表单域内容。
- 解决方法:
直接使用apex_web_service.make_rest_request_blob接收二进制响应,跳过CLOB转BLOB的步骤,避免数据损坏。
2. 多部分请求的Content-Type头缺失
Postman会自动为多部分请求添加正确的Content-Type头(包含边界标识),但原Apex代码未设置该头,导致API无法正确识别请求中的多部分数据,仅解析了JSON部分。
- 解决方法:
显式设置Content-Type为多部分表单格式,结合Apex生成的边界字符串。
3. PDF模板BLOB传递时的潜在损坏
从数据库读取BLOB后,若存在隐式编码转换,可能导致模板内容损坏,API无法正确解析模板的固定文本部分。
- 解决方法:
验证数据库中存储的input_templateBLOB完整性:将BLOB导出为本地PDF文件,确认模板内容正常;传递时直接使用原始BLOB,不做额外转换。
4. 响应头的UTF-8编码设置错误
PDF是二进制文件,无需设置UTF-8文本编码,原代码的owa_util.mime_header中指定UTF-8可能导致下载的PDF文件异常。
- 解决方法:
移除owa_util.mime_header中的UTF-8参数。
修正后的完整代码
DECLARE l_blob BLOB; lm_multipart apex_web_service.t_multipart_parts; lc_json CLOB := '[{ "D1": 194645, "R1": 1, "R2": 9, "R3": 4, "R4": 6, "R5": 4, "R6": 5 }]'; lv_filename VARCHAR2(20) := 'my_file.pdf'; lv_base_url VARCHAR2(100) := 'http://10.50.200.11:27005/report'; -- webservice base URL; lb_blob BLOB; -- Blob part of the multipart BEGIN -- Select unfilled PDF template stored as BLOB in database SELECT input_template INTO lb_blob FROM python_input_template WHERE sno = 1; -- 显式设置所有必要请求头,包括多部分Content-Type apex_web_service.set_request_headers( p_name_01 => 'x-api-key', p_value_01 => 'qwerty_key', p_name_02 => 'x-api-user', p_value_02 => 'APEX', p_name_03 => 'Content-Type', p_value_03 => 'multipart/form-data; boundary=' || apex_web_service.get_boundary(lm_multipart) ); /*Supply data to fill the pdf with*/ apex_web_service.append_to_multipart( p_multipart => lm_multipart, p_name => 'data_str', p_content_type => 'application/json', p_body => lc_json ); /*Supply the template to be filled*/ apex_web_service.append_to_multipart( p_multipart => lm_multipart, p_name => 'template', p_filename => lv_filename, p_content_type => 'application/pdf', p_body_blob => lb_blob ); -- 直接接收二进制响应,避免CLOB转BLOB的损坏风险 l_blob := apex_web_service.make_rest_request_blob( p_url => lv_base_url, p_http_method => 'POST', p_body_blob => apex_web_service.generate_request_body(lm_multipart) ); sys.htp.init; -- PDF是二进制文件,无需指定UTF-8编码 owa_util.mime_header( 'application/pdf', false ); sys.htp.p('Content-Disposition: attachment; filename="' || 'filled_template.pdf' || '"'); sys.htp.p('Content-length: ' || sys.dbms_lob.getlength(l_blob)); sys.owa_util.http_header_close; wpg_docload.download_file(l_blob); apex_application.stop_apex_engine; END;
内容的提问来源于stack exchange,提问作者Arif Sher Khan
相关产品推荐
相关产品推荐

