Oracle UTL_HTTP Post Multipart/Form-Data (JSON & ZIP) Example

Here I am giving an example to send JSON and a Zip file to the REST web service using Oracle UTL_HTTP post multipart/form-data.

Initially, I took the example code from Nick Buytaert's blog and then modified it to incorporate the JSON and the Zip file.

Send JSON and a Zip File to REST web service using UTL_HTTP

The following PL/SQL code will do the REST web service authentication using the Token. And after that, it will get the JSON and the BLOB from the table. It will Zip the BLOB and then combine it with the JSON by converting it to base64 type data. Then it will prepare the header and send it.

declare
l_attachment blob;
l_newline varchar2(50) := chr(13) || chr(10);
lco_boundary constant varchar2(30) := 'gc0p4Jq0M2Yt08jU534c0p';

l_http_request utl_http.req;
l_request_body clob;
l_request_body_length number;
l_req_body clob;
l_http_response utl_http.resp;
l_response_header_name varchar2(256);
l_response_header_value varchar2(1024);
l_response_body varchar2(32767);

l_offset number := 1;
l_amount number := 2000;
l_buffer varchar2(2000);
l_clob clob;
l_token varchar2(32767);
begin
-- get the token
l_clob := apex_web_service.make_rest_request(
 p_url => 'https://YourTokenURL',
 p_http_method => 'GET');
 l_status := apex_web_service.g_status_code;
APEX_JSON.parse(l_clob);
l_token:=APEX_JSON.get_varchar2(p_path => 'token'); 

-- prepare or get the json
l_req_body := '{name: "Scott", age: 33, city: "Huston"}';

l_request_body := l_newline
|| '--' || lco_boundary || l_newline
|| 'Content-Disposition: form-data; name="contact-info"' || l_newline
|| 'Content-Type: application/json' || l_newline
|| l_newline
|| l_req_body; --|| l_newline
--|| '--' || lco_boundary || '--';

-- get the blob from the table and zip it
FOR l_file IN (
SELECT
file_name,
my_file_blob
FROM
my_doc_table
WHERE
doc_id = '1234'
) LOOP
apex_zip.add_file(p_zipped_blob => l_attachment, p_file_name => l_file.file_name,
p_content => l_file.my_file_blob);
END LOOP;

apex_zip.finish(p_zipped_blob => l_attachment);

-- concatenate zip file as base64 data to the above json
l_request_body := l_request_body || l_newline
|| '--' || lco_boundary || l_newline
|| 'Content-Disposition: form-data; name="attachment"' || l_newline
|| 'Content-Type: application/zip' || l_newline
|| 'Content-Transfer-Encoding: base64' || l_newline
|| l_newline
|| apex_web_service.blob2clobbase64(l_attachment) || l_newline
|| '--' || lco_boundary || '--';

dbms_output.put_line('Request body>');
dbms_output.put_line(dbms_lob.substr(l_request_body, 4000, 1));

l_request_body_length := dbms_lob.getlength(l_request_body);

-- authenticate wallet
utl_http.set_wallet(
path => 'file:/your/wallet/path',
password => 'YourWalletPsw'
);

-- start sending the data
l_http_request := utl_http.begin_request(
url => 'https://yourRESTservicePostURL',
method => 'POST',
http_version => 'HTTP/1.1'
);

-- set header
utl_http.set_header(l_http_request, 'Authorization', 'Bearer ' || l_token);
utl_http.set_header(l_http_request, 'Content-Type', 'multipart/form-data; boundary="' || lco_boundary || '"');
utl_http.set_header(l_http_request, 'Content-Length', l_request_body_length);
utl_http.set_header(l_http_request, 'Transfer-Encoding', 'Chunked');
utl_http.set_header(l_http_request, 'Connection', 'keep-alive');

-- send data in chunks
while l_offset < l_request_body_length loop
dbms_lob.read(l_request_body, l_amount, l_offset, l_buffer);
utl_http.write_text(l_http_request, l_buffer);
l_offset := l_offset + l_amount;
end loop;

-- print the response 
l_http_response := utl_http.get_response(l_http_request);
dbms_output.put_line('Response> Status Code: ' || l_http_response.status_code);
dbms_output.put_line('Response> Reason Phrase: ' || l_http_response.reason_phrase);
dbms_output.put_line('Response> HTTP Version: ' || l_http_response.http_version);

for i in 1 .. utl_http.get_header_count(l_http_response) loop
utl_http.get_header(l_http_response, i, l_response_header_name, l_response_header_value);
dbms_output.put_line('Response> ' || l_response_header_name || ': ' || l_response_header_value);
end loop;

utl_http.read_text(l_http_response, l_response_body, 32767);
dbms_output.put_line('Response body>');
dbms_output.put_line(l_response_body);

if l_http_request.private_hndl is not null then
utl_http.end_request(l_http_request);
end if;

if l_http_response.private_hndl is not null then
utl_http.end_response(l_http_response);
end if;
exception
when others then
if l_http_request.private_hndl is not null then
utl_http.end_request(l_http_request);
end if;

if l_http_response.private_hndl is not null then
utl_http.end_response(l_http_response);
end if;

raise;
end;

This code works like a charm. Please let me know in the comment section if you have any issues.

Vinish Kapoor
Vinish Kapoor

Vinish Kapoor is a seasoned software development professional and a fervent enthusiast of artificial intelligence (AI). His impressive career spans over 20 years, marked by a relentless pursuit of innovation and excellence in the field of information technology. As an Oracle ACE, Vinish has distinguished himself as a leading expert in Oracle technologies, a title awarded to individuals who have demonstrated their deep commitment, leadership, and expertise in the Oracle community.

2 Comments

  1. Hi Sir,
    I have one file browse option on a page. User can upload image using file browse after that i want to send the blob another server using post api call using plsql oracle apex.

  2. Hi, when i sending blob objects the files are corrupted at the destinated side i.e. we are unable to open the file. IT seems some encoded issues. I noticed the file size is also change as compare to original size

Comments are closed.