반응형
Oracle에서의 Base64 인코딩 및 디코딩
Oracle에서 Base64 값을 인코딩/디코딩하려면 어떻게 해야 합니까?
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;
먹어봐.
update: 사소한 조정 후에 이 방법이 떠올랐습니다.이 때문에, 현재는 양쪽 모두 동작합니다.
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;
확인할 수 있습니다.
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: 좋습니다.다음은 다음 샘플의 변환입니다.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;
솔루션utl_encode.base64_encode그리고.utl_encode.base64_decode1개의 제한이 있습니다.최대 32,767 문자/바이트의 문자열에서만 동작합니다.
더 큰 현을 변환해야 하는 경우 몇 가지 장애에 직면하게 됩니다.
- 위해서
BASE64_ENCODE함수는 3바이트를 읽고 변환해야 합니다.멀티바이트 문자(예:öäüè€UTF-8에 저장, 일명AL32UTF8) 3 문자는 반드시 3 바이트일 필요는 없습니다.항상 3바이트를 읽으려면 다음 명령을 변환해야 합니다.CLOB안으로BLOB첫번째. - 같은 문제가 에도 적용됩니다.
BASE64_DECODE함수는 4바이트를 읽고 3바이트로 변환해야 합니다.이들 3바이트는 반드시 3자일 필요는 없습니다. - 일반적으로 BASE64-String에는 NEW_LINE이 있습니다(
CR및/또는LF)는, 각 64 문자의 문자입니다.이러한 새 줄 문자는 디코딩 중에 무시해야 합니다.
이 모든 것을 고려해 보면, 풀 기능의 솔루션은 다음과 같습니다.
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;
이전 게시물은 모두 정확합니다.고양이 가죽을 벗기는 방법은 한 가지가 아닙니다.다음은 동일한 작업을 수행하는 다른 방법입니다. ('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;
/
하다url_raw.cast_to_raw()oracle 6에서의 지원
언급URL : https://stackoverflow.com/questions/3804279/base64-encoding-and-decoding-in-oracle
반응형
'programing' 카테고리의 다른 글
| 스프링 MVC 컨트롤러 유닛테스트가 @ControllerAdvice를 호출하지 않음 (0) | 2023.03.18 |
|---|---|
| angular ng-if 또는 ng-show 응답이 느립니다(2초 지연) (0) | 2023.03.18 |
| ASP를 통해 JSON 날짜 값을 전달하는 방법.JSON을 사용한NET MVC인터넷? (0) | 2023.03.18 |
| JSON 어레이를 사용하는 것과 JSON 개체를 사용하는 것의 차이점은 무엇입니까? (0) | 2023.03.18 |
| AngularJS - $http.데이터를 json으로 게시 (0) | 2023.03.13 |