Kir*_*tev 51
我已实现此功能,通过我的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;
Run Code Online (Sandbox Code Playgroud)
试试吧.
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;
Run Code Online (Sandbox Code Playgroud)
你可以检查一下:
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
Run Code Online (Sandbox Code Playgroud)
upd2:好的,这是一个适用于CLOB我想出的样本转换.尝试为你的blob工作.:)
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;
Run Code Online (Sandbox Code Playgroud)
与解决方案utl_encode.base64_encode,并utl_encode.base64_decode有一个限制,他们用绳子多达32,767个字符/字节才有效.
如果你必须转换更大的字符串,你将面临几个障碍.
BASE64_ENCODE函数必须读取3个字节并对其进行转换.在多字节字符的情况下(例如,öäüè€以UTF-8存储,也称为AL32UTF8)3 字符不一定也是3 字节.为了始终读取3个字节,您必须将您转换CLOB为BLOB第一个.BASE64_DECODE.该函数必须读取4个字节并将其转换为3个字节.那3个字节不一定也是3个字符CR和/或LF)字符.解码时必须忽略这些新行字符.考虑到所有这些,全功能的解决方案可能是这样的:
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;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
122564 次 |
| 最近记录: |