如何从 11g Oracle (PL/SQL) 上的 URL 传递凭据和下载文件?
Posted
技术标签:
【中文标题】如何从 11g Oracle (PL/SQL) 上的 URL 传递凭据和下载文件?【英文标题】:How to pass credentials and download file from a URL on 11g Oracle (PL/SQL)? 【发布时间】:2016-01-06 16:19:09 【问题描述】:我正在尝试编写一个 plsql 过程来从另一个系统中的给定 url 下载文件。该系统需要用户名和密码才能访问。当我尝试以下程序时(基本上是这个script),我收到一个错误:
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;
/
【问题讨论】:
【参考方案1】:utl_encode.base64_encode
function 采用 RAW 参数,而不是 VARCHAR2,因此您必须先转换值。您可以在纯 SQL 中看到相同的内容(消息略有不同):
select utl_encode.base64_encode('userid:passwd') from dual;
SQL Error: ORA-01465: invalid hex number
您可以使用utl_i18n.string_to_raw
function 将字符串转换为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 将其显示为ZFhObGNtbGtPbkJoYzNOM1pBPT0=
。但是连接它会使其保持原始形式。
您需要另一个步骤来显式转换为可用的字符串值:
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==
然后与Basic
前缀连接时保留相同的值。
你可以在你的程序中做同样的事情:
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 值首先存储在它们自己的变量中。
【讨论】:
嗨,亚历克斯,你完全正确。这已经摆脱了错误。但我仍然无法获取文件。我收到一个带有“需要授权。此服务器无法验证您是否有权访问所请求的文档”的 htm 文件。 (我已经通过浏览器验证了我正在使用的用户 ID) @manumuraleedharan - 是的,错过了您需要将 RAW 结果转换回字符串。更新了答案以表明这一点。您可能需要检查手动请求的标头(通过浏览器的开发人员工具),以将您获得的 HTTP 标头与生成的 HTTP 标头进行比较。 优秀的@AlexPoole 你又为我节省了时间!问候【参考方案2】:我今天遇到了同样的问题,使用以下方法解决了它:
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 Database EE 11GR2
【讨论】:
以上是关于如何从 11g Oracle (PL/SQL) 上的 URL 传递凭据和下载文件?的主要内容,如果未能解决你的问题,请参考以下文章
从 pl/sql 中的函数返回数据作为光标而不创建类型 oracle 11g
Oracle 11g 代码上的 PL/SQL 是在执行存储过程时
用于 oracle 11g 的 PL/SQL 中的嵌入式脚本 [重复]