This chapter illustrates how to upload data from the Oracle® Database into a remote SFTP server with PL/SQL code. We can upload BLOB and CLOB fields directly into files.
List of Examples
Uploading data
The method for uploading BLOB fields with ORA_SFTP is UPLOAD (or PUT)
In the example below, we will upload an image contained in a customers’ record to a remote SFTP server file location. You have to adapt the code for uploading your own BLOB data:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | DECLARE connection_id NUMBER; private_key_handle BFILE; private_key BLOB; private_key_password VARCHAR2(500); DATA BLOB; BEGIN DBMS_LOB.createtemporary(private_key, TRUE); private_key_handle := BFILENAME('SFTP_KEYS_DIR', 'test_putty_private.ppk'); -- directory name must be Upper case DBMS_LOB.OPEN(private_key_handle, DBMS_LOB.LOB_READONLY); DBMS_LOB.LoadFromFile( private_key, private_key_handle, DBMS_LOB.GETLENGTH(private_key_handle) ); DBMS_LOB.CLOSE(private_key_handle); private_key_password := 'changeit'; SELECT picture_blob INTO DATA FROM customers WHERE customer_id = 100; connection_id := ORA_SFTP.CONNECT_HOST('localhost', 22, 'nasko', private_key, private_key_password); ORA_SFTP.UPLOAD(connection_id, DATA, 'image.png'); ORA_SFTP.DISCONNECT_HOST(connection_id); END; / |
Uploading CLOB fields
The method for uploading CLOB fields with ORA_SFTP is UPLOAD_CLOB.
CLOB fields contain character data and it has to be encoded into bytes in order for the remote file to have a meaning. By default, UPLOAD_CLOB will encode the character data in UTF-8 format, or we can specify the target file encoding as an additional parameter.
In the example below we are going to create dynamically a CSV (comma separated values) report and upload it to an SFTP server. The resulting remote file encoding will be UTF-8.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | DECLARE connection_id NUMBER; private_key_handle BFILE; private_key BLOB; private_key_password VARCHAR2(500); v_clob CLOB; CURSOR C1 IS SELECT EMPNO, ENAME, SAL, E.DEPTNO, DNAME FROM EMP E, DEPT D WHERE E.DEPTNO = D.DEPTNO ORDER BY EMPNO; C1_R C1%ROWTYPE; BEGIN DBMS_LOB.createtemporary(private_key, TRUE); private_key_handle := BFILENAME('SFTP_KEYS_DIR', 'test_putty_private.ppk'); -- directory name must be Upper case DBMS_LOB.OPEN(private_key_handle, DBMS_LOB.LOB_READONLY); DBMS_LOB.LoadFromFile( private_key, private_key_handle, DBMS_LOB.GETLENGTH(private_key_handle) ); DBMS_LOB.CLOSE(private_key_handle); private_key_password := 'changeit'; FOR C1_R IN C1 LOOP v_clob := v_clob || C1_R.EMPNO || ',' || C1_R.ENAME || ',' || C1_R.SAL; v_clob := v_clob || CHR(10) || chr(13); END LOOP; connection_id := ORA_SFTP.CONNECT_HOST('localhost', 22, 'nasko', private_key, private_key_password); ORA_SFTP.UPLOAD_CLOB(connection_id, v_clob, 'EmpoleesReport.csv'); ORA_SFTP.DISCONNECT_HOST(connection_id); END; / |
If for example, we went to specify encoding other than UTF-8 for the remote file, we can achieve this by specifying the encoding as the last parameter like this:
1 | ORA_SFTP.UPLOAD_CLOB(connection_id, v_clob, 'EmpoleesReport.csv', 'UTF-32'); |
A list of the available encodings that we can use is available here.
Retry strategy
Network connections are not reliable and an upload may fail. This is normal and in that case, we have to retry the upload again. Our suggestion is to retry using the overloaded variant of the PUT/UPLOAD method that can customize the upload read/write buffer, by using a rather small value like:
BEGIN Ora_SFTP.put(retry_connection_id, data_blob, 'data.dat'); EXCEPTION WHEN OTHERS THEN BEGIN IF INSTR (SQLERRM, 'Unexpected end of sftp stream') <> 0 THEN Ora_SFTP.DISCONNECT_HOST(retry_connection_id); retry_connection_id := ORA_SFTP.CONNECT_HOST(...); ORA_SFTP.UPLOAD(retry_connection_id, data_blob, 'data.dat', 1024); -- 1KB transfer buffer ELSE ... handle other cases END IF; END; END; |
Secure Copy (SCP)
Most SFTP servers, especially on Unix systems also provide an SCP (secure copy) service that can be used from the same SFTP connection.
SCP is useful when we need more speed (see below) as its protocol doesn’t have the mandatory acknowledgments for each SFTP packet. And despite that, it is as secure as SFTP as it relies on the same authenticated and encrypted connection.
We can perform SCP copy with ORA_SFTP.SCP_UPLOAD:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | DECLARE connection_id NUMBER; private_key_handle BFILE; private_key BLOB; private_key_password VARCHAR2(500); DATA BLOB; BEGIN DBMS_LOB.createtemporary(private_key, TRUE); private_key_handle := BFILENAME('SFTP_KEYS_DIR', 'test_putty_private.ppk'); -- directory name must be Upper case DBMS_LOB.OPEN(private_key_handle, DBMS_LOB.LOB_READONLY); DBMS_LOB.LoadFromFile( private_key, private_key_handle, DBMS_LOB.GETLENGTH(private_key_handle) ); DBMS_LOB.CLOSE(private_key_handle); private_key_password := 'changeit'; SELECT picture_blob INTO DATA FROM customers WHERE customer_id = 100; connection_id := ORA_SFTP.CONNECT_HOST('localhost', 22, 'nasko', private_key, private_key_password); ORA_SFTP.SCP_UPLOAD(connection_id, DATA, 'image.png'); ORA_SFTP.DISCONNECT_HOST(connection_id); END; / |
Performance issues
SFTP speed is limited to around 1.5 MB/s due to the data encryption overhead and the acknowledgment of each SFTP packet.
As of version 1.9.3 OraSFTP provides support for transparent ZLib compression which reduces the data being transferred and increases the speed by 33%. SCP provides a faster transfer speed and if your remote SFTP server supports SCP you can use SCP_UPLOAD instead of UPLOAD.
Below is an excerpt comparing the SFTP upload and SCP upload speeds
File Size | ORA_SFTP.UPLOAD | ORA_SFTP.SCP_UPLOAD |
90 MB | 7 min 38 sec | 5 min 09 sec |
150 MB | 12 min 42 sec | 8 min 56 sec |
Summary
This article discussed how to upload data from inside the Oracle(c) database to a remote SFTP server.
You may also like to read how to download remote files into BLOB and CLOB fields with PL/SQL.