使用 PL/SQL 将 base64 图像解码为 BLOB

Posted

技术标签:

【中文标题】使用 PL/SQL 将 base64 图像解码为 BLOB【英文标题】:Decode base64 image into BLOB with PL/SQL 【发布时间】:2014-11-27 08:34:42 【问题描述】:

我正在使用下面的脚本从 MongoDB 获取 JSON 文件,对其进行解析,然后将其插入 Oracle 表中。

从某种意义上说,该脚本工作正常,它将所有值正确地插入到 Oracle 表中。这包括值 Photo,它是 base64 格式的图像,它远大于 32KB。

Appery_Photos 中的列 Photo 属于 CLOB 类型,而列 DecodedPhoto 属于 BLOB 类型。 p>

问题在于我用来将 CLOB 解码为 BLOB 的行 blobOriginal := base64decode1(Photo);base64decode1 函数已替换为多个函数(即decode_base64、base64DecodeClobAsBlob_plsql、base64decode、from_base64 和最后的JSON_EXT.DECODE)。

结果对所有人来说都是一样的。也就是说,生成的 BLOB 对象不能在任何图像编辑器中作为图像打开(我正在使用 Oracle SQL Developer 下载它)。

我检查了 CLOB,但找不到任何换行符 \n,也找不到任何空格(仅找到 + 符号)。此外,我将 CLOB 值插入base64-image-converter 并正确显示图像。此外,为了进一步验证(使用上面链接中提供的相反函数),我尝试将生成的 BLOB 编码回 base64 中,结果 base64 根本不一样。

开始 l_http_request := UTL_HTTP.begin_request('https://api.appery.io/rest/1/db/collections/Photos?where=%7B%22Oracle_Flag%22%3A%22Y%22%7D' , 'GET' , 'HTTP/1.1'); -- ...设置标题的属性 UTL_HTTP.set_header(l_http_request, 'X-Appery-Database-Id', '53f2dac5e4b02cca64021dbe'); l_http_response := UTL_HTTP.get_response(l_http_request); 开始 环形 UTL_HTTP.read_text(l_http_response, buf); l_response_text := l_response_text ||缓冲区; 结束循环; 例外 当 UTL_HTTP.end_of_body 那么 空值; 结尾; l_list := json_list(l_response_text); FOR i IN 1..l_list.count 环形 A_id := json_ext.get_string(json(l_list.get(i)),'_id'); l_val := json_ext.get_json_value(json(l_list.get(i)),'照片'); dbms_lob.createtemporary(照片,真,2); json_value.get_string(l_val, 照片); dbms_output.put_line(dbms_lob.getlength(照片)); dbms_output.put_line(dbms_lob.substr(照片, 20, 1)); blobOriginal := base64decode1(照片); A_Name := json_ext.get_string(json(l_list.get(i)),'Name'); 备注:= json_ext.get_string(json(l_list.get(i)),'备注'); 状态 := json_ext.get_string(json(l_list.get(i)),'Status'); UserId := json_ext.get_string(json(l_list.get(i)),'UserId'); A_Date := json_ext.get_string(json(l_list.get(i)),'Date'); A_Time := json_ext.get_string(json(l_list.get(i)),'Time'); MSG_status := json_ext.get_string(json(l_list.get(i)),'MSG_status'); Oracle_Flag := json_ext.get_string(json(l_list.get(i)),'Oracle_Flag'); acl := json_ext.get_string(json(l_list.get(i)),'acl'); 插入 INTO Appery_Photos ( 援助, 照片, 解码照片, 一个名字, 评论, 地位, 用户身份, 一个约会, A_时间, 味精状态, Oracle_Flag, acl ) 价值观 ( 援助, 照片, blob原创, 一个名字, 评论, 地位, 用户身份, 一个约会, A_时间, 味精状态, Oracle_Flag, acl ); dbms_lob.freetemporary(照片); 结束循环; -- 最终确定 UTL_HTTP.end_response(l_http_response); 例外 当 UTL_HTTP.end_of_body 那么 UTL_HTTP.end_response(l_http_response); 结尾;

非常感谢任何帮助。

【问题讨论】:

Store big JSON files into Oracle DB 的可能重复项 您已经为这个问题准备了一个问题。使用这些附加详细信息对其进行编辑。 谢谢@JeffreyKemp 我更新了那个。但是,另一个问题是关于将 JSON 读入 Oracle 表。这个问题是关于将 Base64 字段解码为 BLOB 的。这是同一脚本中的另一个问题。 【参考方案1】:

我发现这不在我在base64解码中使用的函数中。相反,我拥有的值不是 base64 编码的字符串,而是 base64 编码的 dataURI,类似于

data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAA

所以我必须使用类似:clobbase642blob(substr(Photo, instr(Photo, ',') + 1))

以下脚本的灵感来自Oracle Community答案

宣布 l_param_list VARCHAR2(512); l_http_request UTL_HTTP.req; l_http_response UTL_HTTP.resp; l_response_text CLOB; --l_response_text VARCHAR2(32767); buf VARCHAR2(32767); l_list json_list; l_val json_value; A_id VARCHAR2(100); 照片CLOB; A_Name VARCHAR2(100); 备注 VARCHAR2(100); 状态 VARCHAR2(100); 用户 ID VARCHAR2(100); A_Date VARCHAR2(100); A_Time VARCHAR2(100); MSG_status VARCHAR2(100); Oracle_Flag VARCHAR2(100); acl VARCHAR2(100); 对象 json_list; blobOriginal BLOB := empty_blob(); clobInBase64 CLOB; 子字符串 VARCHAR2(2000); tmp BLOB; n 请整数:= 0; substring_length pls_integer := 2000; -------------------------------------------------- ---- 函数 clobbase642blob( p_clob CLOB ) 返回斑点 是 t_blob BLOB; t_buffer VARCHAR2(32767); t_pos 编号:= 1; t_size NUMBER := nls_charset_decl_len( 32764, nls_charset_id( 'char_cs' ) ); t_len 号码; t_tmp 原始(32767); 开始 dbms_lob.createtemporary(t_blob, true); t_len := 长度( p_clob ); 环形 出口 当 t_pos > t_len; t_buffer := REPLACE( REPLACE( SUBSTR( p_clob, t_pos, t_size ), chr(10) ), chr(13) ); t_pos := t_pos + t_size; 而 t_pos 0 环形 t_buffer := t_buffer ||替换(替换(SUBSTR(p_clob,t_pos,1),chr(10)),chr(13)); t_pos := t_pos + 1; 结束循环; t_tmp := utl_encode.base64_decode(utl_raw.cast_to_raw(t_buffer)); dbms_lob.writeappend(t_blob,utl_raw.length(t_tmp),t_tmp); 结束循环; 返回t_blob; 结尾; -------------------------------------------------- ---- 开始 -- 服务的输入参数 -- 准备请求... l_http_request := UTL_HTTP.begin_request('https://api.appery.io/rest/1/db/collections/Photos?where=%7B%22Oracle_Flag%22%3A%22Y%22%7D' , 'GET' , 'HTTP/1.1'); -- ...设置标题的属性 UTL_HTTP.set_header(l_http_request, 'X-Appery-Database-Id', '53f2dac5e4b02cca64021dbe'); l_http_response := UTL_HTTP.get_response(l_http_request); 开始 环形 UTL_HTTP.read_text(l_http_response, buf); l_response_text := l_response_text ||缓冲区; 结束循环; 例外 当 UTL_HTTP.end_of_body 那么 空值; 结尾; l_list := json_list(l_response_text); FOR i IN 1..l_list.count 环形 A_id := json_ext.get_string(json(l_list.get(i)),'_id'); --处理base64 URI照片>32KB l_val := json_ext.get_json_value(json(l_list.get(i)),'照片'); dbms_lob.createtemporary(照片,真,2); json_value.get_string(l_val, 照片); --dbms_output.put_line(dbms_lob.getlength(照片)); --dbms_output.put_line(dbms_lob.substr(照片, 20, 1)); blobOriginal := clobbase642blob( SUBSTR( 照片, 24 ) ); A_Name := json_ext.get_string(json(l_list.get(i)),'Name'); 备注:= json_ext.get_string(json(l_list.get(i)),'备注'); 状态 := json_ext.get_string(json(l_list.get(i)),'Status'); UserId := json_ext.get_string(json(l_list.get(i)),'UserId'); A_Date := json_ext.get_string(json(l_list.get(i)),'Date'); A_Time := json_ext.get_string(json(l_list.get(i)),'Time'); MSG_status := json_ext.get_string(json(l_list.get(i)),'MSG_status'); Oracle_Flag := json_ext.get_string(json(l_list.get(i)),'Oracle_Flag'); acl := json_ext.get_string(json(l_list.get(i)),'acl'); 插入 INTO Appery_Photos ( 援助, 照片, 解码照片, 一个名字, 评论, 地位, 用户身份, 一个约会, A_时间, 味精状态, Oracle_Flag, acl ) 价值观 ( 援助, 照片, blob原创, 一个名字, 评论, 地位, 用户身份, 一个约会, A_时间, 味精状态, Oracle_Flag, acl ); dbms_lob.freetemporary(照片); 结束循环; -- 最终确定 UTL_HTTP.end_response(l_http_response); 例外 当 UTL_HTTP.end_of_body 那么 UTL_HTTP.end_response(l_http_response); 结尾; /

【讨论】:

【参考方案2】:

它是 Base64 或 HexBinary...

这适用于十六进制

function DESERIALIZE_HEX_BLOB(P_SERIALIZATION CLOB)
return BLOB
is
  V_BLOB BLOB;
  V_OFFSET INTEGER := 1;
  V_AMOUNT INTEGER := 32000;
  V_INPUT_LENGTH NUMBER := DBMS_LOB.GETLENGTH(P_SERIALIZATION);
  V_HEXBINARY_DATA VARCHAR2(32000);
begin
  if (P_SERIALIZATION is NULL) then return NULL; end if;
  DBMS_LOB.CREATETEMPORARY(V_BLOB,TRUE,DBMS_LOB.CALL);
  while (V_OFFSET <= V_INPUT_LENGTH) loop
    V_AMOUNT := 32000;
    DBMS_LOB.READ(P_SERIALIZATION,V_AMOUNT,V_OFFSET,V_HEXBINARY_DATA);
    V_OFFSET := V_OFFSET + V_AMOUNT;
    DBMS_LOB.APPEND(V_BLOB,TO_BLOB(HEXTORAW(V_HEXBINARY_DATA)));
  end loop;
  return V_BLOB;
end;
--

并且可以修改为处理 Base64 而不会有太多麻烦。

【讨论】:

以上是关于使用 PL/SQL 将 base64 图像解码为 BLOB的主要内容,如果未能解决你的问题,请参考以下文章

如何使用颤振将 Base64 字符串解码为图像文件

在 C# 中将 Base64 字节数组解码为图像

在 Powerapps 中使用 .image 属性将 Base64 字符串解码为图像并显示

在python中将base64编码的图像解码为原始图像

Python 对图像进行base64编码及解码读取为numpyopencvmatplot需要的格式

C# 和 PL/SQL 中的 Base64?