2022年12月7日水曜日

簡単なファイル管理アプリケーションの作成(4) - ファイルをオブジェクト・ストレージに保存する

 Always FreeのAutonomous Databaseのストレージは20GBなので、ちょっとファイルをアップロードすると容量が足りなくなります。ファイルを保存するために、高速なストレージを消費するのも勿体無い話ですし、それだけのために有料インスタンスにアップグレードするのも勿体無い気がします。

とういうことで、ファイルの実体をオブジェクト・ストレージに保存するようにAPEXアプリケーションを改変してみます。

アップロードされたファイルは、オブジェクト・ストレージに以下のように保存されます。


準備


今までの記事に従って、ファイル管理アプリケーションが作成済みであることを前提としています。今回はオブジェクト・ストレージを使うため、以下の記事の記載に従って準備します。

ユーザー、グループ、ポリシーなどの作成を行います。

APEXからOCIオブジェクト・ストレージを操作する(1) - APIユーザーの作成

バケットはapex_file_storageを使います。

PL/SQL SDKを使用するため、以下の記事にあるクリデンシャルの作成とワークスペース・スキーマへの権限の付与も実施します。

APEXからオブジェクト・ストレージをPL/SQL SDKで操作する(1) - 準備

作成されるクリデンシャルはMY_OCI_CREDになります。


表SFM_CONTENTSの変更



オブジェクト・ストレージにファイルを保存すると、全文検索索引の再作成ができなくなります。そのため、索引作成のソースとなる文字列を表SFM_CONTENTSに保存しておきます。

全文検索索引のソースを保存する列TEXT_INDEX_SOURCEを表SFM_CONTENTSに追加します。

alter table sfm_contents add (text_index_source blob);

また、変更回数を記録する列VERSIONも追加します。

alter table sfm_contents add (version number default 0 not null);

クイックSQLのモデルは以下のように変わります。
# prefix: sfm
# pk: guid
contents
    title vc80 /nn
    abstract vc800
    content file
    text_index_source blob
    version num /default 0 /nn

ファイルから全文検索索引のソースとなる文字列を抽出するプロシージャSFM_CONTENTS_DOCは以下に変更します。

ファイルがデータベースにアップロードされたときに、ファイルから文字列を抽出し列TEXT_INDEX_SOURCEに保存していることが前提です。索引を作成する際にファイルのデータを必要としないため、ファイルがオブジェクト・ストレージにあっても全文検索索引を作ることができます。

全文検索索引のソースは文字データなので圧縮することで容量を節約していますが、表自体が圧縮されている場合は不要かもしれません。そうすると列TEXT_INDEX_SOURCEはCLOBで定義できますが、今回は手が込んでいる方がサンプルとして使い勝手が良いだろうと判断し、圧縮して保存するようにしています。

表SFM_CONTENTSに列が追加されたため、ページ番号のフォームSfm Contentページ・アイテムの同期化を実行すると、ページ・アイテムP3_TEXT_INDEX_SOURCEP3_VERSIONが追加されます。このページ・アイテムにユーザーがデータを入力することは無いため、ビルド・オプションコメント・アウトしておきます。




オブジェクト・ストレージのアクセス情報の設定



ファイルを保存するオブジェクト・ストレージに関する情報を、アプリケーション定義置換文字列として設定します。

G_REGION - リージョン(今回の例ではus-ashburn-1
G_NAMESPACE - オブジェクト・ストレージのネームスペース
G_BUCKET - バケット名(今回の例ではapex_file_storage
G_CREDENTIAL - クリデンシャル(今回の例ではMY_OCI_CRED

置換文字列の設定では前後の空白はトリムされないため、不要な空白が入っていないか注意が必要です。



プロシージャとパッケージの作成



TEXT_INDEX_SOURCEにデータを保存するプロシージャretrieve_text_index_sourceを作成します。このデータが全文検索索引の作成時に使用されます。

SQLワークショップSQLコマンドに貼り付けて実行します。


次に、オブジェクト・ストレージにファイルをアップロードするプロシージャupload_fileとダウンロードするプロシージャdownload_file、および削除するプロシージャdelete_fileを実装したパッケージsfm_file_utilを作成します。

コードは以下になります。

SQLワークショップSQLスクリプトとして実行します。


確認画面が開くので、即時実行をクリックします。


パッケージパッケージ本体が作成されたことを確認します。




アップロード処理の変更



ページ・デザイナにてページ番号のフォームのページを開きます。

プロシージャretrieve_text_index_sourceを呼び出すプロセスを作成します。

プロセスの作成を実行し、新規に作成されたプロセスをプロセス・フォームSfm Contentの下に配置します。

識別名前文字列の抽出とし、タイプAPIの呼び出しを選択します。設定タイプとしてPL/SQL Procedure or Function所有者Parsing Schemaとし、プロシージャまたはファンクションとしてRETRIEVE_TEXT_INDEX_SOURCEを選択します。

サーバー側の条件タイプとしてリクエスト値に含まれるを選択し、CREATE SAVEを入力します。ボタン作成および変更の適用を押したとき(ボタン削除では実行しない)に、プロセス文字列の抽出を実行します。


パラメータp_idには、ページ・アイテムP3_IDの値を渡します。


同様にパッケージ・プロシージャupload_fileを呼び出すプロセスを作成します。

識別名前ファイルのアップロード設定タイプPL/SQL PackageパッケージSFM_FILE_UTILプロシージャまたはファンクションとしてUPOAD_FILEを選択します。

このプロセスも、ボタン作成または変更の適用がクリックされたときに実行します。


パラメータp_idにはページ・アイテムP3_IDの値を渡します。それ以外は、置換文字列として設定したG_REGIONG_NAMESPACEG_BUCKETG_CREDENTIALの値を渡します。


アップロードするファイルが指定されていないときは、文字列の抽出ファイルのアップロードが実行されないよう、その前にダイアログを閉じます。

プロセスを作成し、プロセス・フォームSfm Contentの直下に配置します。

識別名前ダイアログを閉じる - ファイル無しタイプとしてダイアログを閉じるを選択します。サーバー側の条件タイプとしてアイテムはNULLを選択し、アイテムとしてP3_CONTENTを選びます。


以上でオブジェクト・ストレージへのファイルのアップロードが実装できました。

アプリケーションからファイルをアップロードしても、列Cotentには何も表示されません。列CONTENTが空になっているためです。




ファイルの削除



ファイルが削除されたときに、オブジェクト・ストレージ上のファイルも削除します。

プロセスを作成します。識別名前ファイルの削除とします。

プロセス・フォームSfm Contentの直下に配置します。パラメータの設定はファイルのアップロードと同じ設定になります。

設定プロシージャまたはファンクションとしてDELETE_FILEを選択し、サーバー側の条件ボタン押下時としてDELETEを選択します。



ダウンロード処理の変更



列CONTENTの内容の代わりに、オブジェクト・ストレージ上のファイルをダウンロードするように処理を変更します。

ページ番号downloadのページに作成したプロセスダウンロードを、パッケージSFM_FILE_UTILDOWNOAD_FILEを呼び出すように変更します。


パラメータp_idへはアイテムIDを渡します。それ以外はアップロードのプロセスと同じく、オブジェクト・ストレージに関する置換文字列を指定します。


ファイルをオブジェクト・ストレージに配置しても、対話モード・レポートの列Download Urlは変わらず有効です。このURLからファイルをダウンロードできます。



ダウンロード・リンクの調整



対話モード・レポートからファイルをダウンロードする方法を変更します。

列CONTENTはつねに空なので、ソースとなるSELECT文より除きます。



列TITLEをクリックしてファイルのダウンロードが開始するよう、列の書式HTML式として以下を記述します。

<a href="#DOWNLOAD_URL#&session=&APP_SESSION.">#TITLE#</a>


ページ番号のフォームに含まれるページ・アイテムP3_CONTENT設定ダウンロード・リンクの表示OFFに変更します。


以上でアプリケーションは完成です。

今回作成した作成したアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/simple-file-manager-obs.zip

Oracle APEXのアプリケーション作成の参考になれば幸いです。