如何在11g Oracle(PL/SQL)上传递凭据并从URL下载文件



我正在尝试编写一个plsql过程,以便从另一个系统中的给定url下载文件。此系统需要用户ID和密码才能访问。当我尝试以下过程(基本上是这个脚本)时,我得到了一个错误:

ORA-06502:PL/SQL:数字或值错误:十六进制到原始转换错误

它来自这条线路:utl_http.set_header(l_http_request, 'Authorization', 'Basic ' || utl_encode.base64_encode('userid:passwd'));我添加它是为了传递凭据。

如果我评论它,这个错误会消失,但我得到:Authorization Required.This server could not verify that you are authorized to access the document requested."

程序代码为:

CREATE OR REPLACE PROCEDURE APPS.load_binary_from_url (p_url  IN  VARCHAR2) AS 
  l_http_request   UTL_HTTP.req;
  l_http_response  UTL_HTTP.resp;
  l_blob           BLOB;
  l_raw            RAW(32767);
  l_url            VARCHAR2(300); 
BEGIN
  -- Initialize the BLOB.
  DBMS_LOB.createtemporary(l_blob, FALSE);  
  l_url :=p_url; 
  -- Make a HTTP request and get the response.
  l_http_request  := UTL_HTTP.begin_request(l_url); 
  utl_http.set_header(l_http_request, 'Authorization', 'Basic ' || utl_encode.base64_encode('userid:passwd'));
  l_http_response := UTL_HTTP.get_response(l_http_request);
  -- Copy the response into the BLOB.
  BEGIN
    LOOP
        UTL_HTTP.read_raw(l_http_response, l_raw, 32767);
        DBMS_LOB.writeappend (l_blob, UTL_RAW.length(l_raw), l_raw);
    END LOOP;
  EXCEPTION
    WHEN UTL_HTTP.end_of_body THEN
      UTL_HTTP.end_response(l_http_response);
  END;
  -- Insert the data into the table.
  INSERT INTO http_blob_test (id, url, data)
  VALUES (http_blob_test_seq.NEXTVAL, p_url, l_blob);
  COMMIT;
  -- Relase the resources associated with the temporary LOB.
  DBMS_LOB.freetemporary(l_blob);
EXCEPTION
  WHEN OTHERS THEN
    UTL_HTTP.end_response(l_http_response);
    DBMS_LOB.freetemporary(l_blob);
    RAISE;
END load_binary_from_url;
/

utl_encode.base64_encode函数采用RAW参数,而不是VARCHAR2,因此必须首先转换值。您可以在普通SQL:中看到相同的内容(但消息略有不同)

select utl_encode.base64_encode('userid:passwd') from dual;
SQL Error: ORA-01465: invalid hex number

您可以使用utl_i18n.string_to_raw函数将字符串转换为RAW:

select utl_encode.base64_encode(utl_i18n.string_to_raw('userid:passwd', 'AL32UTF8'))
from dual;
UTL_ENCODE.BASE64_ENCODE(UTL_I18N.STRING_TO_RAW('USERID:PASSWD','AL32UTF8'))   
--------------------------------------------------------------------------------
64584E6C636D6C6B4F6E426863334E335A413D3D                                        

取决于您的客户端和设置,这些设置可能显示为如上所述,或者隐式显示为从原始转换回;例如SQL Fiddle将其显示为CCD_ 5。但将其连接起来会使其处于原始形式。

您需要另一个步骤来显式转换为可用的字符串值:

select utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_i18n.string_to_raw('userid:passwd', 'AL32UTF8'))) from dual;
UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(UTL_I18N.STRING_TO_RAW('USERID
--------------------------------------------------------------------------------
dXNlcmlkOnBhc3N3ZA==                                                            

并且随后当与CCD_ 6前缀连接时保留相同的值。

你可以在你的程序中做同样的事情:

  utl_http.set_header(l_http_request, 'Authorization',
    'Basic ' || utl_raw.cast_to_varchar2(utl_encode.base64_encode(
      utl_i18n.string_to_raw('userid:passwd', 'AL32UTF8'))));

可选地将RAW值首先存储在它们自己的变量中以便于易读。

我今天遇到了同样的问题,使用解决了这个问题

  utl_http.set_header(l_http_request, 'Authorization',
    'Basic ' || utl_raw.cast_to_varchar2(utl_encode.base64_encode(
      utl_i18n.string_to_raw('userid:passwd', 'UTF8'))));

注意:我使用的是Oracle数据库EE 11GR2

最新更新