Multipart/Form-Data requests with APEX_WEB_SERVICE

As the demand for web applications grows, developers have had to find new ways to build their applications faster and more efficiently. In recent years, Oracle Database has become an invaluable tool for developers, offering powerful capabilities like APEX_WEB_SERVICE. In this blog post, we will explore the benefits of using APEX_WEB_SERVICE to send multipart/form requests with ease.

What is a Multipart/Form Request?

A multipart/form request is an HTTP request that contains a combination of structured data and files. This type of request is used in situations where we need to send data in different formats. By using a multipart/form request, the data can be split into multiple parts and sent in a single HTTP request.

Since version 20.2, the APEX_WEB_SERVICE API supports multipart/form requests, making it much easier to work with web services. This means that with minimal code, developers can quickly and easily make calls to web services without having to worry about the complexities of constructing and sending the request.

For those using APEX versions older than 20.2, the UTL_HTTP package can be used instead. This package is the predecessor of APEX_WEB_SERVICE and provides similar functionality, though it may require more code and effort to get it to work correctly.

Overall, both APEX_WEB_SERVICE and UTL_HTTP are useful tools for communicating with web services. The newer and improved APEX_WEB_SERVICE API is the preferred solution, as it is easier to use and requires less code, but the UTL_HTTP package is still a viable option for older versions of APEX.

In the example below, the web-service being called requires three different parts which are being sent together as part of a single request. The first part is a JSON parameter application which is sent as application/json, the second part is a plain text file which is sent as text/plain and the third part is a file application which is sent as application/octet-stream.

DECLARE
       lc_response      clob;
       lm_multipart     apex_web_service.t_multipart_parts;
       ln_email_address VARCHAR2(100) := 'email_adress@email.com';
       lc_json          clob          := '{"hello":"world"}';   
       lv_filename      VARCHAR2(20)  := 'my_file';
       lv_base_url      VARCHAR2(100); -- webservice base URL; 
       lv_api_key       VARCHAR2(100); -- API KEY 
       lb_blob          blob; -- Blob part of the multipart

BEGIN

        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 := lv_api_key;   

        /* add a CLOB (JSON) to a multipart/form request body */
        IF lc_json is not null 
        THEN
        apex_web_service.APPEND_TO_MULTIPART (
                p_multipart    => lm_multipart,
                p_name         => 'json_param',
                p_content_type => 'application/json',
                p_body         => lc_json );
        END IF;

        /* add a plain text to a multipart/form request body */
        IF ln_email_address is not null
        THEN        
        apex_web_service.APPEND_TO_MULTIPART (
                p_multipart    => lm_multipart,
                p_name         => 'email_address',
                p_content_type => 'text/plain',
                p_body         => ln_email_address ); 
        END IF;        

        /*add a BLOB to a multipart/form request body.*/        
        apex_web_service.APPEND_TO_MULTIPART (
                p_multipart    => lm_multipart,
                p_name         => 'filename',
                p_filename     => lv_filename,
                p_content_type => 'application/octet-stream',
                p_body_blob    => lb_blob );

        l_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)); 

        -- generate_request_body: This function generates the multipart/form-data request body from the data in the t_multiparts array.

        dbms_output.put_line(l_response);                      

END;

It is important to be aware that, when dealing with BLOB files, all of the parameters used above must be used; otherwise, an error message that is not very helpful will be displayed. It is not stated in the Oracle documentation, and it took me a while to identify the problem.

6
Subscribe to my newsletter

Read articles from Rodrigo Mesquita directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Rodrigo Mesquita
Rodrigo Mesquita

Rodrigo is a Senior Oracle Developer at QV Systems. He is an experienced software engineer with emphasis in analysis, design and development of bespoke Oracle applications utilising development tools such as APEX, PL / SQL, jQuery, javaScript, CSS and JSON for a variety of international businesses. Rodrigo speaks regularly at Oracle community events and enjoys creating APEX plugins and writing blogs.