如何用PL/SQL向Web服务发送multipart/form-data格式图片并添加参数
问题修正与参数添加方案
一、现有代码的已知问题修正
你当前的代码存在逻辑错误,会导致请求体格式异常:
- 你已经将图片转成Base64写入了
p_request_body,后续又把原始二进制图片l_attachment追加到blb中,相当于重复提交了两次图片数据,格式完全不符合multipart规范,这是你请求异常的核心原因之一 - 重复设置了
Content-Type请求头,多余的设置可以直接删除
二、添加请求参数的方法
1. 添加URL查询参数(对应你Postman示例中的subject=56543参数)
直接修改p_url变量,把参数拼接到URL末尾即可,示例:
-- 原p_url修改为带查询参数的格式 p_url VARCHAR2(255) := 'http://192.168.0.120:8000/api/v1/recognition/faces?subject=56543';
如果参数是动态值,用字符串拼接即可,注意特殊字符要做URL转义,可调用utl_url.escape()函数处理参数值。
2. 添加multipart/form-data普通表单参数
如果参数需要放在请求体的form字段里,直接在p_request_body的文件字段前面追加普通字段的multipart结构即可,示例:
p_request_body := l_newline || '--' || lco_boundary || l_newline || -- 普通表单参数subject 'Content-Disposition: form-data; name="subject"' || l_newline || l_newline || '56543' || l_newline || -- 原有文件字段 '--' || lco_boundary || l_newline || 'Content-Disposition: form-data; name="file"; filename="' || l_file_name || '"' || l_newline || 'Content-Type: ' || l_mime_type || l_newline || 'Content-Transfer-Encoding: base64' || l_newline || l_newline || apex_web_service.blob2clobbase64(l_attachment) || l_newline || '--' || lco_boundary || '--';
注意:这里把chunked改成了base64,和实际的图片编码格式保持一致。
三、修正后核心代码片段
删掉多余的dbms_lob.append(blb, l_attachment);语句,因为你已经把Base64编码的图片写入到p_request_body里了,不需要再追加原始二进制图片:
-- 原有converttoblob之后直接删除append语句 dbms_lob.createtemporary(blb, FALSE); dest_offset := 1; src_offset := 1; lang_context := 0; dbms_lob.converttoblob(blb, p_request_body, dbms_lob.getlength(p_request_body), dest_offset, src_offset, 0, lang_context, warning); -- 删掉这行:dbms_lob.append(blb, l_attachment); req_length := dbms_lob.getlength(blb); -- 删掉多余的第一个Content-Type设置 -- utl_http.set_header(utl_req, 'content-type', 'multipart/form-data'); 该设置重复,下方已有带boundary的正确设置
四、可选简化方案
你使用的是APEX 21.1,可以直接调用原生的apex_web_service.make_rest_request接口发送multipart请求,不需要手动拼接边界和编码,代码更简洁不易出错:
DECLARE l_response CLOB; l_attachment BLOB; l_file_name VARCHAR2(255); l_mime_type VARCHAR2(255); BEGIN SELECT IMAGE, FILENAME, MIMETYPE INTO l_attachment, l_file_name, l_mime_type FROM TEST_TABLE WHERE ID_ID = 21; -- 设置请求头 apex_web_service.g_request_headers.delete(); apex_web_service.g_request_headers(1).name := 'x-api-key'; apex_web_service.g_request_headers(1).value := 'ce83481a-701f-xxxx-a3ec-exxxxxb5665e'; -- 发送请求,自动处理multipart格式 l_response := apex_web_service.make_rest_request( p_url => 'http://192.168.0.120:8000/api/v1/recognition/faces?subject=56543', p_http_method => 'POST', p_body_blob => l_attachment, p_body_blob_mime_type => l_mime_type, p_body_blob_parameter_name => 'file', p_body_blob_filename => l_file_name ); -- 输出响应 dbms_output.put_line('响应状态:'||apex_web_service.g_status_code); dbms_output.put_line('响应内容:'||l_response); END; /
内容的提问来源于stack exchange,提问作者Amit Dabhekar
相关产品推荐
相关产品推荐

