Apex 20.1
I have an interactive report which has one clickable column that I used to download a file from Apex to the user's computer.
Originally I had the link call an application process which worked beautifully. However I found that larger files would take time to download, and there was no "spinning circle" to indicate that the user should keep waiting, or that anything was happening.
So I put the download code in an "After Submit" process with a "Request=" server-side condition.

The link from my interactive report now calls the process with a URL thus:

javascript:var submit =apex.submit({request:"FETCH_ATTACHMENT", showWait:true, set:{"P4_MESSAGE_ID":#MESSAGE_ID#, "P4_PART_ID":#PART_ID#, "P4_PART_NAME":"#PART_NAME#"}});
The "showWait" works beautifully now, I get a spinning circle, except now I have the opposite problem. After the download is finished, the page is still greyed-out with the spinning circle. The only way to bring it back is to refresh the page.

I would like the spinning circle to go away once the file is downloaded and control to be returned back to the page.
Here is the code, it's still in dev so excuse the debug untidiness!
DECLARE
vclob CLOB;
vclobtmp CLOB;
vblob BLOB;
vmimetype VARCHAR2(1000);
v_position INTEGER;
v_progress VARCHAR2(100);
v_error varchar2(1000);
FUNCTION Clobfromblob (p_blob BLOB)
RETURN CLOB
IS
l_clob CLOB;
l_dest_offsset INTEGER := 1;
l_src_offsset INTEGER := 1;
l_lang_context INTEGER := dbms_lob.default_lang_ctx;
l_warning INTEGER;
BEGIN
IF p_blob IS NULL THEN
RETURN NULL;
END IF;
dbms_lob.Createtemporary(lob_loc => l_clob, CACHE => FALSE);
dbms_lob.Converttoclob(dest_lob => l_clob, src_blob => p_blob,
amount => dbms_lob.lobmaxsize, dest_offset => l_dest_offsset,
src_offset => l_src_offsset, blob_csid => dbms_lob.default_csid,
lang_context => l_lang_context, warning => l_warning);
RETURN l_clob;
END;
BEGIN
--raise_application_error(-20000,'P4_MESSAGE_ID '||:P4_MESSAGE_ID||' P4_PART_ID '||:P4_PART_ID||' :P4_PART_NAME '||:P4_PART_NAME);
delete from apps.barry_debug;
insert into apps.barry_debug(time,debug) values (sysdate, 'start1'); commit;
dbms_lob.Createtemporary(lob_loc => vclob, CACHE => TRUE,
dur => dbms_lob.call);
dbms_lob.Createtemporary(lob_loc => vclobtmp, CACHE => TRUE,
dur => dbms_lob.call);
dbms_lob.Createtemporary(lob_loc => vblob, CACHE => TRUE,
dur => dbms_lob.call);
SELECT part_data,
Substr(part_type, 1, Instr(part_type, ';') - 1)
INTO vblob, vmimetype
FROM source_data
WHERE message_id = :P4_MESSAGE_ID --APEX_APPLICATION.g_x01
AND part_id = :P4_PART_ID --APEX_APPLICATION.g_x02
;
v_progress := 'blob to clob';
insert into apps.barry_debug(time,debug) values (sysdate, 'clob1'); commit;
vclobtmp := Clobfromblob(vblob);
--Strip the header from the attachment data
v_position := dbms_lob.Instr(vclobtmp, 'Content-Transfer-Encoding: base64',
1, 1
)
+ 33;
dbms_lob.Copy(vclob, vclobtmp, dbms_lob.Getlength(vclobtmp), 1, v_position);
v_progress := 'decodebase64';
insert into apps.barry_debug(time,debug) values (sysdate, 'decodebase'); commit;
vblob := apex_web_service.Clobbase642blob(vclob);
--vblob := apps.P_Base64.DecodeToBlob (vClob);
sys.htp.init;
v_progress := 'mime_header';
sys.owa_util.Mime_header(vmimetype /*'application/octet-stream'*/, FALSE
/*,'UTF-8' */);
sys.htp.P('Content-length: '
|| sys.dbms_lob.Getlength(vblob));
sys.htp.P('Content-Disposition: attachment; filename="'
||:P4_PART_NAME
||'"');
sys.owa_util.http_header_close;
v_progress := 'download_file';
insert into apps.barry_debug(time,debug) values (sysdate, 'download'); commit;
sys.wpg_docload.Download_file(vblob);
insert into apps.barry_debug(time,debug) values (sysdate, 'release1'); commit;
dbms_lob.Freetemporary (vblob); --do not forget!!
insert into apps.barry_debug(time,debug) values (sysdate, 'release2'); commit;
dbms_lob.Freetemporary (vclob); --do not forget!!
insert into apps.barry_debug(time,debug) values (sysdate, 'release3'); commit;
dbms_lob.Freetemporary (vclobtmp); --do not forget!!
apex_application.stop_apex_engine; --this is needed to download file in background. But it raises an exception below.
insert into apps.barry_debug(time,debug) values (sysdate, 'finished'); commit;
EXCEPTION
when apex_application.e_stop_apex_engine then
raise; -- raise again the stop Application Express engine exception
WHEN no_data_found THEN
NULL;
when others then
--raise_application_error(-20000,'Error-fetch-attachment-'||v_progress||' '||sqlerrm);
v_error := sqlerrm;
insert into apps.barry_debug(time,debug) values (sysdate, 'Error-fetch-attachment-'||v_progress||'*'||v_error);
END;
The Debugging table shows that processing ends after the engine is stopped. (If I take this out nothing downloads at all).
