それらのプロセスを組み込んだアプリケーションの画面です。
このAPEXアプリケーションのエクスポートを以下に置いています。
https://github.com/ujnak/apexapps/blob/master/exports/blob-handling.zip
機能はすべてホーム・ページに実装しています。
タイプがファイルのアップロードであるページ・アイテムP1_FILEを作成しています。このページ・アイテムのストレージのタイプに表APEX_APPLICATION_TEMP_FILESを選択することで、ボタンSUBMITをクリックしたときに実行されるプロセス内で、アップロードされたファイルをAPEX_APPLICATION_TEMP_FILESの列BLOB_CONTENTより、BLOBとして取り出せます。
- BLOB2BASE64_PLSQL - PL/SQLでBLOBをBase64エンコードしたCLOBへ変換します。結果をAPEXコレクションに保存します。
- BLOB2BASE64_JS - JavaScriptでBLOBをBase64エンコードしたCLOBへ変換します。結果をAPEXコレクションに保存します。
- BASE642BLOB_PLSQL - JavaScriptで変換したBase64のCLOBを、PL/SQLでBLOBへ変換します。結果をAPEXコレクションに保存します。
- BASE642BLOB_JS - PL/SQLで変換したBase64のCLOBを、JavaScriptでBLOBへ変換します。結果をAPEXコレクションに保存します。
変換結果はすべてAPEXコレクションに保存されます。変換結果を確認するために、以下のSELECT文をソースとしたクラシック・レポートを作成しています。
select
seq_id,
c001,
substr(clob001,1,60) clob001,
dbms_lob.getlength(blob001) blob001
from apex_collections
where collection_name = :P1_COLLECTION_NAME
CLOBについては先頭60バイトが一致していれば、JavaScriptとPL/SQLの双方の変換で同じ、BLOBについては全体の長さが一致していればJavaScriptとPL/SQLの双方の変換で同じだろうと見做しています。より厳密さを求めるのであれば、DBMS_CRYPTO.HASHの利用も考慮する必要があります。パッケージDBMS_CRYPTOはデフォルトでは実行権限がなく、管理者によるGRANT文の実行が必要なためレポートに含めていません。
PL/SQLによるBLOBからBase64エンコードされたCLOBへの変換は、以下のコードで行なっています。Oracle APEXが提供しているAPEX_WEB_SERVICE.BLOB2CLOBBASE64を呼び出しています。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare | |
C_THIS_PROCESS_NAME constant varchar2(80) := 'BLOB2BASE64_PLSQL'; | |
l_blob blob; | |
l_base64 clob; | |
begin | |
/* | |
* アップロードされたファイルをBLOBとして取り出す。 | |
*/ | |
select blob_content into l_blob from apex_application_temp_files | |
where name = :P1_FILE; | |
/* | |
* PL/SQLによるBLOBからBASE64でエンコードしたCLOBへの変換には | |
* APEX_WEB_SERVICE.BLOB2CLOBBASE64を呼び出す。 | |
*/ | |
l_base64 := apex_web_service.blob2clobbase64(l_blob,'N','N'); | |
/* | |
* 結果をAPEXコレクションにCLOBとして保存する。 | |
*/ | |
apex_collection.add_member( | |
p_collection_name => :P1_COLLECTION_NAME | |
,p_c001 => C_THIS_PROCESS_NAME | |
,p_clob001 => l_base64 | |
); | |
end; |
JavaScriptによるBLOBからBase64エンコードされたCLOBへの変換は、以下のコードで行なっています。Oracleが提供しているモジュールmle-encode-base64に含まれるファンクションencodeを呼び出しています。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const {encode: base64encode, decode: base64decode} = await import('mle-encode-base64'); | |
const C_THIS_PROCESS_NAME = 'BLOB2BASE64_JS'; | |
const collection_name = apex.env.P1_COLLECTION_NAME; | |
/* | |
* アップロードされたファイルをBLOBとして取り出す。 | |
*/ | |
const name = apex.env.P1_FILE; | |
const result = apex.conn.execute( | |
`select blob_content from apex_application_temp_files where name = :name`, | |
{ | |
name: { | |
type: oracledb.DB_TYPE_VARCHAR, | |
dir: oracledb.BIND_IN, | |
val: name | |
} | |
}, | |
{ | |
fetchInfo: { | |
"BLOB_CONTENT": { | |
type: oracledb.ORACLE_BLOB | |
} | |
} | |
} | |
); | |
if (result.rows.length === 0) { | |
throw new Error(`No data found for name ${name}`); | |
} | |
else | |
{ | |
// 検索結果は必ず1行のみ。 | |
for (let row of result.rows) { | |
/* | |
* JavaScriptによるBLOBからBASE64でエンコードしたCLOBへの変換は | |
* モジュールmle-encode-base64に含まれているencodeを呼び出す。 | |
*/ | |
const blob = row.BLOB_CONTENT; | |
const base64string = base64encode(blob.getData()); | |
/* | |
* 結果をAPEXコレクションにCLOBとして保存する。 | |
*/ | |
apex.conn.execute( | |
`begin apex_collection.add_member(p_collection_name => :col, p_c001 => :c001, p_clob001 => :clob001 ); end;`, | |
{ | |
col: { | |
type: oracledb.DB_TYPE_VARCHAR, | |
dir: oracledb.BIND_IN, | |
val: collection_name | |
}, | |
c001: { | |
type: oracledb.DB_TYPE_VARCHAR, | |
dir: oracledb.BIND_IN, | |
val: C_THIS_PROCESS_NAME | |
}, | |
clob001: { | |
type: oracledb.DB_TYPE_CLOB, | |
dir: oracledb.BIND_IN, | |
val: base64string | |
} | |
} | |
); | |
}; | |
}; |
PL/SQLによるBase64エンコードされたCLOBからBLOBへの変換は、以下のコードで行なっています。Oracle APEXが提供しているAPEX_WEB_SERVICE.CLOBBASE642BLOBを呼び出しています。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare | |
C_THIS_PROCESS_NAME constant varchar2(80) := 'BASE642BLOB_PLSQL'; | |
C_SOURCE_PROCESS_NAME constant varchar2(80) := 'BLOB2BASE64_JS'; | |
l_blob blob; | |
l_base64 clob; | |
begin | |
/* | |
* JavaScriptでBase64に変換したCLOBを取り出す。 | |
*/ | |
select clob001 into l_base64 from apex_collections | |
where collection_name = :P1_COLLECTION_NAME and C001 = C_SOURCE_PROCESS_NAME; | |
/* | |
* PL/SQLによるBASE64でエンコードしたCLOBからBLOBへの変換には | |
* APEX_WEB_SERVICE.CLOBBASE642BLOBを呼び出す。 | |
*/ | |
l_blob := apex_web_service.clobbase642blob(l_base64); | |
/* | |
* 結果をAPEXコレクションにBLOBとして保存する。 | |
*/ | |
apex_collection.add_member( | |
p_collection_name => :P1_COLLECTION_NAME | |
,p_c001 => C_THIS_PROCESS_NAME | |
,p_blob001 => l_blob | |
); | |
end; |
JavaScriptによるBase64エンコードされたCLOBからBLOBへの変換は、以下のコードで行なっています。Oracleが提供しているモジュールmle-encode-base64に含まれるファンクションdecodeを呼び出しています。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const {encode: base64encode, decode: base64decode} = await import('mle-encode-base64'); | |
const C_THIS_PROCESS_NAME = 'BLOB2BASE64_JS'; | |
const C_SOURCE_PROCESS_NAME = 'BLOB2BASE64_PLSQL'; | |
const collection_name = apex.env.P1_COLLECTION_NAME; | |
/* | |
* PL/SQLでBase64に変換したCLOBを取り出す。 | |
*/ | |
const name = apex.env.P1_FILE; | |
const result = apex.conn.execute( | |
`select clob001 from apex_collections where collection_name = :collection_name and c001 = :c001`, | |
{ | |
collection_name: { | |
type: oracledb.DB_TYPE_VARCHAR, | |
dir: oracledb.BIND_IN, | |
val: collection_name | |
}, | |
c001: { | |
type: oracledb.DB_TYPE_VARCHAR, | |
dir: oracledb.BIND_IN, | |
val: C_SOURCE_PROCESS_NAME | |
} | |
}, | |
{ | |
fetchInfo: { | |
"CLOB001": { | |
type: oracledb.ORACLE_CLOB | |
} | |
} | |
} | |
); | |
if (result.rows.length === 0) { | |
throw new Error(`No data found for c001 ${c001}`); | |
} | |
else | |
{ | |
// 検索結果は必ず1行のみ。 | |
for (let row of result.rows) { | |
/* | |
* JavaScriptによるBASE64でエンコードしたCLOBからBLOBへの変換は | |
* モジュールmle-encode-base64に含まれているdecodeを呼び出す。 | |
*/ | |
const base64 = row.CLOB001; | |
const bytes = base64decode(base64.getData()); | |
const blob = OracleBlob.createTemporary(false); | |
blob.open(OracleBlob.LOB_READWRITE); | |
blob.write(1, bytes); | |
/* | |
* 結果をAPEXコレクションにBLOBとして保存する。 | |
*/ | |
apex.conn.execute( | |
`begin apex_collection.add_member(p_collection_name => :col, p_c001 => :c001, p_blob001 => :blob001 ); end;`, | |
{ | |
col: { | |
type: oracledb.DB_TYPE_VARCHAR, | |
dir: oracledb.BIND_IN, | |
val: collection_name | |
}, | |
c001: { | |
type: oracledb.DB_TYPE_VARCHAR, | |
dir: oracledb.BIND_IN, | |
val: C_THIS_PROCESS_NAME | |
}, | |
blob001: { | |
type: oracledb.DB_TYPE_BLOB, | |
dir: oracledb.BIND_IN, | |
val: blob | |
} | |
} | |
); | |
blob.close(); | |
blob.freeTemporary(); | |
}; | |
}; |
今回の記事は以上になります。
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完