oracle oracle中的base64编解码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3804279/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 02:47:40  来源:igfitidea点击:

Base64 encoding and decoding in oracle

oraclebase64

提问by Pradeep

How can I do Base64 encode/decode a value in Oracle?

如何在 Oracle 中对值进行 Base64 编码/解码?

回答by Kirill Leontev

I've implemented this to send Cyrillic e-mails through my MS Exchange server.

我已经实现了这一点,通过我的 MS Exchange 服务器发送西里尔文电子邮件。

function to_base64(t in varchar2) return varchar2 is
 begin
    return utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(t)));
end to_base64;

Try it.

尝试一下。

upd:after a minor adjustment I came up with this, so it works both ways now:

upd:经过轻微调整后,我想出了这个,所以现在它可以双向工作:

function from_base64(t in varchar2) return varchar2 is
begin
  return utl_raw.cast_to_varchar2(utl_encode.base64_decode(utl_raw.cast_to_raw(t)));
end from_base64;

You can check it:

你可以检查一下:

SQL> set serveroutput on
SQL> 
SQL> declare
  2    function to_base64(t in varchar2) return varchar2 is
  3    begin
  4      return utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(t)));
  5    end to_base64;
  6  
  7    function from_base64(t in varchar2) return varchar2 is
  8    begin
  9      return utl_raw.cast_to_varchar2(utl_encode.base64_decode(utl_raw.cast_to_raw    (t)));
 10    end from_base64;
 11  
 12  begin
 13    dbms_output.put_line(from_base64(to_base64('asdf')));
 14  end;
 15  /

asdf

PL/SQL procedure successfully completed

upd2:Ok, here's a sample conversion that works for CLOBI just came up with. Try to work it out for your blobs. :)

upd2:好的,这是CLOB我刚想出的适用于的示例转换。尝试为您的斑点解决这个问题。:)

declare

  clobOriginal     clob;
  clobInBase64     clob;
  substring        varchar2(2000);
  n                pls_integer := 0;
  substring_length pls_integer := 2000;

  function to_base64(t in varchar2) return varchar2 is
  begin
    return utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(t)));
  end to_base64;

  function from_base64(t in varchar2) return varchar2 is
  begin
    return utl_raw.cast_to_varchar2(utl_encode.base64_decode(utl_raw.cast_to_raw(t)));
  end from_base64;

begin

  select clobField into clobOriginal from clobTable where id = 1;

  while true loop

    /*we substract pieces of substring_length*/
    substring := dbms_lob.substr(clobOriginal,
                                 least(substring_length, substring_length * n + 1 - length(clobOriginal)),
                                 substring_length * n + 1);  
    /*if no substring is found  - then we've reached the end of blob*/

    if substring is null then
      exit;
    end if;  

    /*convert them to base64 encoding and stack it in new clob vadriable*/
    clobInBase64 := clobInBase64 || to_base64(substring);          
    n := n + 1;  

  end loop;

  n := 0;
  clobOriginal := null;

  /*then we do the very same thing backwards - decode base64*/
  while true loop 

    substring := dbms_lob.substr(clobInBase64,
                                 least(substring_length, substring_length * n + 1 - length(clobInBase64)),
                                 substring_length * n + 1);  
    if substring is null then
      exit;
    end if;  
    clobOriginal := clobOriginal || from_base64(substring);  
    n := n + 1;  
  end loop; 

      /*and insert the data in our sample table - to ensure it's the same*/
  insert into clobTable (id, anotherClobField) values (1, clobOriginal);

end;

回答by Wernfried Domscheit

Solution with utl_encode.base64_encodeand utl_encode.base64_decodehave one limitation, they work only with strings up to 32,767 characters/bytes.

与解决方案utl_encode.base64_encode,并utl_encode.base64_decode有一个限制,他们用绳子多达32,767个字符只工作/字节。

In case you have to convert bigger strings you will face several obstacles.

如果您必须转换更大的字符串,您将面临几个障碍。

  • For BASE64_ENCODEthe function has to read 3 Bytesand transform them. In case of Multi-Byte characters (e.g. ??üèstored at UTF-8, aka AL32UTF8) 3 Characterare not necessarily also 3 Bytes. In order to read always 3 Bytes you have to convert your CLOBinto BLOBfirst.
  • The same problem applies for BASE64_DECODE. The function has to read 4 Bytes and transform them into 3 Bytes. Those 3 Bytesare not necessarily also 3 Characters
  • Typically a BASE64-String has NEW_LINE (CRand/or LF) character each 64 characters. Such new-line characters have to be ignored while decoding.
  • 因为BASE64_ENCODE函数必须读取 3 个字节并转换它们。在多字节字符的情况下(例如??üè存储在 UTF-8,又名AL32UTF8) 3 Character不一定也是 3 Bytes。为了始终读取 3 字节,您必须先将其转换CLOBBLOB
  • 同样的问题适用于BASE64_DECODE. 该函数必须读取 4 个字节并将它们转换为 3 个字节。那些 3 个字节不一定也是 3 个字符
  • 通常 BASE64-String每 64 个字符有一个 NEW_LINE(CR和/或LF)字符。解码时必须忽略此类换行符。

Taking all this into consideration the full featured solution could be this one:

考虑到所有这些,全功能解决方案可能是这样的:

CREATE OR REPLACE FUNCTION DecodeBASE64(InBase64Char IN OUT NOCOPY CLOB) RETURN CLOB IS

    blob_loc BLOB;
    clob_trim CLOB;
    res CLOB;

    lang_context INTEGER := DBMS_LOB.DEFAULT_LANG_CTX;
    dest_offset INTEGER := 1;
    src_offset INTEGER := 1;
    read_offset INTEGER := 1;
    warning INTEGER;
    ClobLen INTEGER := DBMS_LOB.GETLENGTH(InBase64Char);

    amount INTEGER := 1440; -- must be a whole multiple of 4
    buffer RAW(1440);
    stringBuffer VARCHAR2(1440);
    -- BASE64 characters are always simple ASCII. Thus you get never any Mulit-Byte character and having the same size as 'amount' is sufficient

BEGIN

    IF InBase64Char IS NULL OR NVL(ClobLen, 0) = 0 THEN 
        RETURN NULL;
    ELSIF ClobLen<= 32000 THEN
        RETURN UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_DECODE(UTL_RAW.CAST_TO_RAW(InBase64Char)));
    END IF;        
    -- UTL_ENCODE.BASE64_DECODE is limited to 32k, process in chunks if bigger    

    -- Remove all NEW_LINE from base64 string
    ClobLen := DBMS_LOB.GETLENGTH(InBase64Char);
    DBMS_LOB.CREATETEMPORARY(clob_trim, TRUE);
    LOOP
        EXIT WHEN read_offset > ClobLen;
        stringBuffer := REPLACE(REPLACE(DBMS_LOB.SUBSTR(InBase64Char, amount, read_offset), CHR(13), NULL), CHR(10), NULL);
        DBMS_LOB.WRITEAPPEND(clob_trim, LENGTH(stringBuffer), stringBuffer);
        read_offset := read_offset + amount;
    END LOOP;

    read_offset := 1;
    ClobLen := DBMS_LOB.GETLENGTH(clob_trim);
    DBMS_LOB.CREATETEMPORARY(blob_loc, TRUE);
    LOOP
        EXIT WHEN read_offset > ClobLen;
        buffer := UTL_ENCODE.BASE64_DECODE(UTL_RAW.CAST_TO_RAW(DBMS_LOB.SUBSTR(clob_trim, amount, read_offset)));
        DBMS_LOB.WRITEAPPEND(blob_loc, DBMS_LOB.GETLENGTH(buffer), buffer);
        read_offset := read_offset + amount;
    END LOOP;

    DBMS_LOB.CREATETEMPORARY(res, TRUE);
    DBMS_LOB.CONVERTTOCLOB(res, blob_loc, DBMS_LOB.LOBMAXSIZE, dest_offset, src_offset,  DBMS_LOB.DEFAULT_CSID, lang_context, warning);

    DBMS_LOB.FREETEMPORARY(blob_loc);
    DBMS_LOB.FREETEMPORARY(clob_trim);
    RETURN res;    

END DecodeBASE64;




CREATE OR REPLACE FUNCTION EncodeBASE64(InClearChar IN OUT NOCOPY CLOB) RETURN CLOB IS

    dest_lob BLOB;  
    lang_context INTEGER := DBMS_LOB.DEFAULT_LANG_CTX;
    dest_offset INTEGER := 1;
    src_offset INTEGER := 1;
    read_offset INTEGER := 1;
    warning INTEGER;
    ClobLen INTEGER := DBMS_LOB.GETLENGTH(InClearChar);

    amount INTEGER := 1440; -- must be a whole multiple of 3
    -- size of a whole multiple of 48 is beneficial to get NEW_LINE after each 64 characters 
    buffer RAW(1440);
    res CLOB := EMPTY_CLOB();

BEGIN

    IF InClearChar IS NULL OR NVL(ClobLen, 0) = 0 THEN 
        RETURN NULL;
    ELSIF ClobLen <= 24000 THEN
        RETURN UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(UTL_RAW.CAST_TO_RAW(InClearChar)));
    END IF;
    -- UTL_ENCODE.BASE64_ENCODE is limited to 32k/(3/4), process in chunks if bigger    

    DBMS_LOB.CREATETEMPORARY(dest_lob, TRUE);
    DBMS_LOB.CONVERTTOBLOB(dest_lob, InClearChar, DBMS_LOB.LOBMAXSIZE, dest_offset, src_offset, DBMS_LOB.DEFAULT_CSID, lang_context, warning);
    LOOP
        EXIT WHEN read_offset >= dest_offset;
        DBMS_LOB.READ(dest_lob, amount, read_offset, buffer);
        res := res || UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(buffer));       
        read_offset := read_offset + amount;
    END LOOP;
    DBMS_LOB.FREETEMPORARY(dest_lob);
    RETURN res;

END EncodeBASE64;

回答by grepit

All the previous posts are correct. There's more than one way to skin a cat. Here is another way to do the same thing: (just replace "what_ever_you_want_to_convert" with your string and run it in Oracle:

之前的所有帖子都是正确的。给猫剥皮的方法不止一种。这是做同样事情的另一种方法:(只需将“what_ever_you_want_to_convert”替换为您的字符串并在 Oracle 中运行它:

    set serveroutput on;
    DECLARE
    v_str VARCHAR2(1000);
    BEGIN
    --Create encoded value
    v_str := utl_encode.text_encode
    ('what_ever_you_want_to_convert','WE8ISO8859P1', UTL_ENCODE.BASE64);
    dbms_output.put_line(v_str);
    --Decode the value..
    v_str := utl_encode.text_decode
    (v_str,'WE8ISO8859P1', UTL_ENCODE.BASE64);
    dbms_output.put_line(v_str);
    END;
    /

source

来源

回答by vikas

do url_raw.cast_to_raw()support in oracle 6

url_raw.cast_to_raw()在 oracle 6 中做支持