You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何去除Oracle中UTL_HTTP.read_text响应的HTTP头信息

解决UTL_HTTP.read_text读取WSDL响应时混入HTTP头的问题

嘿,我之前也踩过一模一样的坑!咱们来拆解问题,然后彻底搞定它:

你用UTL_HTTP.read_text替代UTL_HTTP.read_line来处理超长请求数据,这完全符合Ask Tom的建议,但为啥前者会带出HTTP头相关内容(比如那个烦人的“Servlet/2.5 JSP/2.1”),后者却不会?

核心原因很简单:UTL_HTTP.read_line默认会自动跳过所有HTTP响应头,直接定位到响应体开始读取;但read_text没有这个默认行为——它会从当前的读取位置开始,把所有内容(包括还没处理的头信息)一股脑读出来。

解决步骤

要搞定这个问题,关键是先显式处理完所有HTTP响应头,再读取响应体,具体操作如下:

1. 先跳过所有HTTP响应头

我们可以通过循环调用UTL_HTTP.next_header遍历所有响应头,直到触发end_of_headers异常(这说明头已经处理完,接下来就是响应体了):

BEGIN
    LOOP
        UTL_HTTP.next_header(l_http_resp);
    END LOOP;
EXCEPTION
    WHEN UTL_HTTP.end_of_headers THEN
        NULL; -- 到头了,直接退出循环即可
END;

2. 读取纯响应体内容

处理完头之后,再用UTL_HTTP.read_text循环读取响应体,把内容写入CLOB:

LOOP
    BEGIN
        UTL_HTTP.read_text(l_http_resp, l_text, 32767);
        DBMS_LOB.writeappend(l_ws_response, LENGTH(l_text), l_text);
    EXCEPTION
        WHEN UTL_HTTP.end_of_body THEN
            EXIT; -- 读取完所有响应体,退出循环
    END;
END LOOP;

完整示例代码

把这些步骤整合到你的程序里,完整代码大概是这样:

DECLARE
    l_http_resp   UTL_HTTP.RESPONSE;
    l_text        VARCHAR2(32767);
    l_ws_response CLOB;
BEGIN
    -- 初始化临时CLOB存储响应内容
    DBMS_LOB.createtemporary(l_ws_response, TRUE);
    
    -- 假设你已经完成请求发送,获取了l_http_resp对象
    -- 第一步:跳过所有HTTP响应头
    BEGIN
        LOOP
            UTL_HTTP.next_header(l_http_resp);
        END LOOP;
    EXCEPTION
        WHEN UTL_HTTP.end_of_headers THEN
            NULL;
    END;
    
    -- 第二步:循环读取响应体内容
    LOOP
        BEGIN
            UTL_HTTP.read_text(l_http_resp, l_text, 32767);
            DBMS_LOB.writeappend(l_ws_response, LENGTH(l_text), l_text);
        EXCEPTION
            WHEN UTL_HTTP.end_of_body THEN
                EXIT;
        END;
    END LOOP;
    
    -- 这里可以处理你的响应内容了,比如解析XML
    -- DBMS_OUTPUT.put_line(l_ws_response);
    
    -- 清理资源
    DBMS_LOB.freetemporary(l_ws_response);
    UTL_HTTP.end_response(l_http_resp);
EXCEPTION
    WHEN OTHERS THEN
        -- 异常处理:确保关闭响应对象和释放CLOB
        IF UTL_HTTP.response_p(l_http_resp) THEN
            UTL_HTTP.end_response(l_http_resp);
        END IF;
        IF DBMS_LOB.istemporary(l_ws_response) THEN
            DBMS_LOB.freetemporary(l_ws_response);
        END IF;
        RAISE;
END;
/

额外注意点

如果你的响应是分块编码的(比如响应头里有Transfer-Encoding: chunked),不用担心,Oracle 11g及以上版本的UTL_HTTP会自动解码分块内容,不需要额外处理。如果是更低版本,可能需要手动处理,但现在应该很少用到了。

内容的提问来源于stack exchange,提问作者Anish Gopinath

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:57:07