Sorry, I was being a bit lazy. Here's how to read chunks in build a larger blob with debugging output so you can follow
SQL> create table t ( b blob);
Table created.
SQL> declare
2 b1 blob;
3 begin
4 insert into t values (utl_raw.cast_to_raw('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJC'))
5 returning b into b1;
6
7 for i in 1 .. 1000
8 loop
9 dbms_lob.writeappend(b1,
10 64,
11 utl_raw.cast_to_raw('asdasdasdAAQSkZJRgABAQAAAQABAAD2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJC')
12 );
13 end loop;
14 commit;
15 end;
16 /
PL/SQL procedure successfully completed.
SQL>
SQL> select dbms_lob.getlength(b) from t;
DBMS_LOB.GETLENGTH(B)
---------------------
64084
1 row selected.
SQL> select dbms_lob.instr(b,utl_raw.cast_to_raw(';base64')) from t;
DBMS_LOB.INSTR(B,UTL_RAW.CAST_TO_RAW(';BASE64'))
------------------------------------------------
16
1 row selected.
SQL>
SQL>
SQL> variable output blob;
SQL> set serverout on
SQL> declare
2 l_idx int;
3 l_len int;
4 l_blob blob;
5 begin
6 select b into l_blob from t;
7 dbms_lob.createtemporary(:output,true);
8 l_idx := 8+dbms_lob.instr(l_blob,utl_raw.cast_to_raw(';base64'));
9 l_len := dbms_lob.getlength(l_blob);
10 dbms_output.put_line('l_idx ' || l_idx );
11 dbms_output.put_line('l_len ' || l_len );
12
13 for i in 1 .. trunc((l_len-l_idx)/2000)+1
14 loop
15 dbms_output.put_line('start ' || l_idx );
16 dbms_output.put_line('amount ' ||least(2000,l_len-l_idx));
17
18 dbms_lob.writeappend(:output,
19 least(2000,l_len-l_idx),
20 dbms_lob.substr(l_blob,least(2000,l_len-l_idx),l_idx)
21 );
22 l_idx := l_idx + 2000;
23 end loop;
24 end;
25 /
l_idx 24
l_len 64084
start 24
amount 2000
start 2024
amount 2000
start 4024
amount 2000
start 6024
amount 2000
start 8024
amount 2000
start 10024
amount 2000
start 12024
amount 2000
start 14024
amount 2000
start 16024
amount 2000
start 18024
amount 2000
start 20024
amount 2000
start 22024
amount 2000
start 24024
amount 2000
start 26024
amount 2000
start 28024
amount 2000
start 30024
amount 2000
start 32024
amount 2000
start 34024
amount 2000
start 36024
amount 2000
start 38024
amount 2000
start 40024
amount 2000
start 42024
amount 2000
start 44024
amount 2000
start 46024
amount 2000
start 48024
amount 2000
start 50024
amount 2000
start 52024
amount 2000
start 54024
amount 2000
start 56024
amount 2000
start 58024
amount 2000
start 60024
amount 2000
start 62024
amount 2000
start 64024
amount 60
PL/SQL procedure successfully completed.
SQL>
SQL> select dbms_lob.getlength(:output) from dual;
DBMS_LOB.GETLENGTH(:OUTPUT)
---------------------------
64060
1 row selected.
SQL>