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

时间:2014-11-27 08:34:43

标签: json plsql oracle11g

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

  • 该脚本在某种意义上可以正常地将所有值插入到Oracle表中。这包括值 Photo ,这是base64 formate的图像,它远大于32KB。
  • Appery_Photos 中的列 Photo 属于CLOB类型,而 DecodedPhoto 列属于BLOB类型。

  • 问题在于我用来将CLOB解码为BLOB的行blobOriginal := base64decode1(Photo);。函数 base64decode1 已被多个函数替换(即decode_base64base64DecodeClobAsBlob_plsqlbase64decodefrom_base64& finally JSON_EXT.DECODE

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

  • 我查了CLOB,找不到任何新行 \ n ,也找不到任何空格(只找到+符号)。此外,我将CLOB值插入base64-image-converter并正确显示图像。另外,为了进一步验证(使用上面链接中提供的相反功能),我尝试在base64中编码生成的BLOB,结果base64完全不同。

     BEGIN
      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');
      -- ...set header's attributes
      UTL_HTTP.set_header(l_http_request, 'X-Appery-Database-Id', '53f2dac5e4b02cca64021dbe');
      l_http_response := UTL_HTTP.get_response(l_http_request);
      BEGIN
        LOOP
          UTL_HTTP.read_text(l_http_response, buf);
          l_response_text := l_response_text || buf;
        END LOOP;
      EXCEPTION
      WHEN UTL_HTTP.end_of_body THEN
        NULL;
      END;
      l_list := json_list(l_response_text);
      FOR i IN 1..l_list.count
      LOOP
        A_id  := json_ext.get_string(json(l_list.get(i)),'_id');
        l_val := json_ext.get_json_value(json(l_list.get(i)),'Photo');
        dbms_lob.createtemporary(Photo, true, 2);
        json_value.get_string(l_val, Photo);
        dbms_output.put_line(dbms_lob.getlength(Photo));
        dbms_output.put_line(dbms_lob.substr(Photo, 20, 1));
        blobOriginal := base64decode1(Photo);
        A_Name       := json_ext.get_string(json(l_list.get(i)),'Name');
        Remarks      := json_ext.get_string(json(l_list.get(i)),'Remarks');
        Status       := 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');
      INSERT
        INTO Appery_Photos
          (
            A_id,
            Photo,
            DecodedPhoto,
            A_Name,
            Remarks,
            Status,
            UserId,
            A_Date,
            A_Time,
            MSG_status ,
            Oracle_Flag,
           acl
          )
          VALUES
          (
            A_id,
            Photo,
            blobOriginal,
            A_Name,
            Remarks,
            Status,
            UserId,
            A_Date,
            A_Time,
            MSG_status ,
            Oracle_Flag,
            acl
          );
        dbms_lob.freetemporary(Photo);
      END LOOP;
      -- finalizing
      UTL_HTTP.end_response(l_http_response);
    EXCEPTION
    WHEN UTL_HTTP.end_of_body THEN
      UTL_HTTP.end_response(l_http_response);
    END;

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:0)

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

数据:图像/ JPEG; BASE64,/ 9J / 4AAQSkZJRgABAQAAA

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

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

DECLARE
  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);
  Photo CLOB;
  A_Name      VARCHAR2(100);
  Remarks     VARCHAR2(100);
  Status      VARCHAR2(100);
  UserId      VARCHAR2(100);
  A_Date      VARCHAR2(100);
  A_Time      VARCHAR2(100);
  MSG_status  VARCHAR2(100);
  Oracle_Flag VARCHAR2(100);
  acl         VARCHAR2(100);
  obj json_list;
  blobOriginal BLOB := empty_blob();
  clobInBase64 CLOB;
  substring VARCHAR2(2000);
  tmp BLOB;
  n pls_integer                := 0;
  substring_length pls_integer := 2000;
  ------------------------------------------------------
  FUNCTION clobbase642blob(
      p_clob CLOB )
    RETURN BLOB
  IS
    t_blob BLOB;
    t_buffer VARCHAR2(32767);
    t_pos    NUMBER := 1;
    t_size   NUMBER := nls_charset_decl_len( 32764, nls_charset_id( 'char_cs' ) );
    t_len    NUMBER;
    t_tmp raw(32767);
  BEGIN
    dbms_lob.createtemporary( t_blob, true );
    t_len := LENGTH( p_clob );
    LOOP
      EXIT
    WHEN 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;
      WHILE t_pos  0
      LOOP
        t_buffer := t_buffer || REPLACE( REPLACE( SUBSTR( p_clob, t_pos, 1 ), chr(10) ), chr(13) );
        t_pos    := t_pos + 1;
      END LOOP;
      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 );
    END LOOP;
    RETURN t_blob;
  END;
  ------------------------------------------------------
  BEGIN
    -- service's input parameters
    -- preparing Request...
    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');
    -- ...set header's attributes
    UTL_HTTP.set_header(l_http_request, 'X-Appery-Database-Id', '53f2dac5e4b02cca64021dbe');
    l_http_response := UTL_HTTP.get_response(l_http_request);
    BEGIN
      LOOP
        UTL_HTTP.read_text(l_http_response, buf);
        l_response_text := l_response_text || buf;
      END LOOP;
    EXCEPTION
    WHEN UTL_HTTP.end_of_body THEN
      NULL;
    END;
    l_list := json_list(l_response_text);
    FOR i IN 1..l_list.count
    LOOP
      A_id := json_ext.get_string(json(l_list.get(i)),'_id');
      --deal with base64 URI photo >32KB
      l_val := json_ext.get_json_value(json(l_list.get(i)),'Photo');
      dbms_lob.createtemporary(Photo, true, 2);
      json_value.get_string(l_val, Photo);
      --dbms_output.put_line(dbms_lob.getlength(Photo));
      --dbms_output.put_line(dbms_lob.substr(Photo, 20, 1));
      blobOriginal := clobbase642blob( SUBSTR( Photo, 24 ) );
      A_Name       := json_ext.get_string(json(l_list.get(i)),'Name');
      Remarks      := json_ext.get_string(json(l_list.get(i)),'Remarks');
      Status       := 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');
      INSERT
      INTO Appery_Photos
        (
          A_id,
          Photo,
          DecodedPhoto,
          A_Name,
          Remarks,
          Status,
          UserId,
          A_Date,
          A_Time,
          MSG_status ,
          Oracle_Flag,
          acl
        )
        VALUES
        (
          A_id,
          Photo,
          blobOriginal,
          A_Name,
          Remarks,
          Status,
          UserId,
          A_Date,
          A_Time,
          MSG_status ,
          Oracle_Flag,
          acl
        );
      dbms_lob.freetemporary(Photo);
    END LOOP;
    -- finalizing
    UTL_HTTP.end_response(l_http_response);
  EXCEPTION
  WHEN UTL_HTTP.end_of_body THEN
    UTL_HTTP.end_response(l_http_response);
  END;
  /

答案 1 :(得分:0)

它是Base64或HexBinary ...

这适用于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。