declare t_conn utl_tcp.connection; t_blob blob; t_clob clob; t_reply number; type tp_dir_listing is table of varchar2(32767) index by pls_integer; t_dir_listing tp_dir_listing; -- g_response varchar2(1000 char); g_wallet_path varchar2(1000 char); g_wallet_password varchar2(1000 char); -- function read_reply( p_conn in out nocopy utl_tcp.connection, p_verbose boolean := true ) return number is t_line varchar(32767); t_code varchar2(3 char); begin t_line := utl_tcp.get_line( p_conn, true ); if nvl( length( t_line ), 0 ) < 4 or substr( t_line, 4, 1 ) not in ( ' ', '-' ) then raise_application_error( -20001, 'Not a valid reply from FTP server: ' || t_line, true ); end if; t_code := substr( t_line, 1, 3 ); g_response := substr( t_line, 5 ); loop if p_verbose then dbms_output.put_line( t_line ); end if; exit when substr( t_line, 1, 4 ) = t_code || ' '; t_line := utl_tcp.get_line( p_conn, true ); end loop; return to_number( t_code ); end; -- function write_cmd( p_conn in out nocopy utl_tcp.connection, p_cmd varchar2, p_param varchar2 := '' ) return number is t_dummy pls_integer; begin t_dummy := utl_tcp.write_line( p_conn, p_cmd || rtrim( ' ' || p_param ) ); return read_reply( p_conn ); end; -- function open_data_channel( p_conn in out nocopy utl_tcp.connection ) return utl_tcp.connection is t_tmp varchar2(32767); t_host varchar2(1000 char); t_port pls_integer; t_conn utl_tcp.connection; begin if write_cmd( p_conn, 'PASV' ) != 227 then raise_application_error( -20001, 'Could not set PASSIVE: ' || g_response, true ); end if; t_tmp := g_response; if ( instr( t_tmp, '(' ) > 0 and instr( t_tmp, '(', 1, 2 ) = 0 and instr( t_tmp, ')' ) > 0 and instr( t_tmp, ')', 1, 2 ) = 0 ) then t_tmp := substr( t_tmp, instr( t_tmp, '(' ) + 1 ); t_tmp := substr( t_tmp, 1, instr( t_tmp, ')' ) - 1 ); else t_tmp := translate( t_tmp, '1234567890,' || t_tmp, '1234567890,' ); end if; t_host := substr( t_tmp, 1, instr( t_tmp, ',', 1, 4 ) - 1 ); t_host := replace( t_host, ',', '.' ); t_tmp := substr( t_tmp, instr( t_tmp, ',', 1, 4 ) + 1 ); t_port := to_number( substr( t_tmp, 1, instr( t_tmp, ',' ) - 1 ) ); t_port := t_port * 256; t_port := t_port + to_number( substr( t_tmp, instr( t_tmp, ',' ) + 1 ) ); t_conn := utl_tcp.open_connection( t_host, t_port, wallet_path => g_wallet_path, wallet_password => g_wallet_password ); return t_conn; end; -- function login ( p_host varchar2 , p_usr varchar2 := null , p_pw varchar2 := null , p_port number := 21 , p_account varchar2 := null , p_wallet_path varchar2 := null , p_wallet_password varchar2 := null ) return utl_tcp.connection is t_reply number; t_conn utl_tcp.connection; t_usr varchar2(1000 char); t_pw varchar2(1000 char); t_acc varchar2(1000 char); begin t_conn := utl_tcp.open_connection( p_host, p_port, wallet_path => p_wallet_path, wallet_password => p_wallet_password ); -- open connection case read_reply( t_conn ) when 120 then raise_application_error( -20001, 'FTP server not ready: ' || g_response, true ); when 421 then raise_application_error( -20001, 'FTP server not available: ' || g_response, true ); else null; end case; if write_cmd( t_conn, 'AUTH', 'TLS' ) = 234 then utl_tcp.secure_connection( t_conn ); if write_cmd( t_conn, 'PBSZ', '0' ) = 200 and write_cmd( t_conn, 'PROT', 'P' ) = 200 then g_wallet_path := p_wallet_path; g_wallet_password := p_wallet_password; end if; end if; if p_usr is null then t_usr := 'anonymous'; t_pw := 'anonymous@mysite.com'; t_acc := '*********'; else t_usr := p_usr; t_pw := p_pw; t_acc := p_account; end if; t_reply := write_cmd( t_conn, 'USER', t_usr ); if t_reply = 331 then t_reply := write_cmd( t_conn, 'PASS', t_pw ); end if; if t_reply = 332 then t_reply := write_cmd( t_conn, 'ACCT', t_acc ); end if; if t_reply not in ( 230, 202 ) then raise_application_error( -20001, 'Could not log in: ' || g_response, true ); end if; return t_conn; end; -- procedure get_file ( p_conn in out nocopy utl_tcp.connection , p_path in varchar2 , p_file in out blob ) is t_reply number; t_buf raw(32767); t_cnt pls_integer; t_conn utl_tcp.connection; begin t_reply := write_cmd( p_conn, 'TYPE', 'I' ); t_conn := open_data_channel( p_conn ); t_reply := write_cmd( p_conn, 'RETR', p_path ); if t_reply in ( 125, 150 ) then if g_wallet_path is not null then utl_tcp.secure_connection( t_conn ); end if; dbms_lob.createtemporary( p_file, true ); begin loop t_cnt := utl_tcp.read_raw( t_conn, t_buf, 32767 ); dbms_lob.writeappend( p_file, t_cnt, t_buf ); end loop; exception when utl_tcp.end_of_input then null; end; utl_tcp.close_connection( t_conn ); t_reply := read_reply( p_conn ); end if; if t_reply not in ( 226, 250 ) then raise_application_error( -20001, 'Could not retrieve file: ' || g_response, true ); end if; end; -- procedure get_file ( p_conn in out nocopy utl_tcp.connection , p_path in varchar2 , p_file in out clob ) is t_reply number; t_buf varchar2(32767); t_cnt pls_integer; t_conn utl_tcp.connection; begin t_reply := write_cmd( p_conn, 'TYPE', 'A' ); t_conn := open_data_channel( p_conn ); t_reply := write_cmd( p_conn, 'RETR', p_path ); if t_reply in ( 125, 150 ) then if g_wallet_path is not null then utl_tcp.secure_connection( t_conn ); end if; dbms_lob.createtemporary( p_file, true ); begin loop t_buf := utl_i18n.raw_to_char( utl_tcp.get_raw( t_conn, 32767 ), 'US7ASCII' ); dbms_lob.writeappend( p_file, length( t_buf ), t_buf ); end loop; exception when utl_tcp.end_of_input then null; end; utl_tcp.close_connection( t_conn ); t_reply := read_reply( p_conn ); end if; if t_reply not in ( 226, 250 ) then raise_application_error( -20001, 'Could not retrieve file: ' || g_response, true ); end if; end; -- procedure nlst ( p_conn in out nocopy utl_tcp.connection , p_dir_listing in out tp_dir_listing , p_path in varchar2 := null ) is t_reply number; t_conn utl_tcp.connection; begin p_dir_listing.delete; t_reply := write_cmd( p_conn, 'TYPE', 'A' ); t_conn := open_data_channel( p_conn ); t_reply := write_cmd( p_conn, 'NLST', p_path ); if t_reply in ( 125, 150 ) then if g_wallet_path is not null then utl_tcp.secure_connection( t_conn ); end if; begin loop p_dir_listing( p_dir_listing.count + 1 ) := utl_tcp.get_line( t_conn, true ); end loop; exception when utl_tcp.end_of_input then null; end; utl_tcp.close_connection( t_conn ); t_reply := read_reply( p_conn ); end if; if t_reply != 226 then raise_application_error( -20001, 'Could not get NLST: ' || g_response, true ); end if; end; -- begin t_conn := login( 'localhost', p_wallet_path => 'file:C:\oracle\wallet', p_wallet_password => 'amis.rules.again' ); -- get_file( t_conn, '/my_dir/my_ascii_file.txt', t_clob ); nlst( t_conn, t_dir_listing, '*.txt' ); t_reply := write_cmd( t_conn, 'QUIT' ); utl_tcp.close_connection( t_conn ); end; /