以前にLouis Moreauxさんの記事を読んでCKEditor5で画像の貼り付けをできるようにしました。以下の記事です。
CKEditor5による画像アップロードを実装する(1) - 準備CKEditor5による画像アップロードを実装する(2) - REST APIの作成
CKEditor5による画像アップロードを実装する(3) - 完成
Allow group APEXObjectManagers to read buckets in compartment APEX
Allow group APEXObjectManagers to manage objects in compartment APEX
APEXからOCIオブジェクト・ストレージを操作する(1) - APIユーザーの作成
さらにLouis MoreauxさんはCKEditor5 Image Upload - Part 3として、画像をデータベースではなくオブジェクト・ストレージに保存する方法を記事として公開しています。
CKEditor5に画像を含めると、文書にを表示する際に含まれている画像を同時にダウンロードするようです。そのため、この機能を組み込んだAPEXアプリケーションをリソース制限の厳しいAlways FreeのAutonomous Database上で動かすと、データベースのセッション数の上限に達してしまいます。
少し残念だったので、画像をオブジェクト・ストレージに保存するように変更して、少ないリソースでもアプリが使えるかどうか確認してみます。
以下は、事前に実施する準備作業です。
ユーザー、グループ、ポリシーなどの作成を行います。事前承認リスエストを生成するため、バケットの権限はreadではなくmanageが必要です。
Allow group APEXObjectManagers to read buckets in compartment APEX
Allow group APEXObjectManagers to manage objects in compartment APEX
APEXからOCIオブジェクト・ストレージを操作する(1) - APIユーザーの作成
バケットはapex_file_storageの代わりにimagesを作成します。
OCI側の準備は以上になります。これから画像をオブジェクト・ストレージに保存するように、アプリケーションに変更を加えます。
RESTサービスのPOSTハンドラの変更
画像のアップロードを受け付けて、BLOBに保存している処理をオブジェクト・ストレージに保存するように変更します。CKEditor5に戻すURLとしてRESTサービスのGETハンドラではなく、オブジェクト・ストレージにアップロードした画像のURLを返します。
ネームスペース名は適切な値に置き換えます。
置換文字列の準備
コード中で使用する各種パラメータを置換文字列として定義します。
G_OBJECT_STORAGE_URLとして、以下を設定します。リージョン名、ネームスペース名、バケット名の値を置き換えます。
https://objectstorage.リージョン名.oraclecloud.com/n/ネームスペース名/b/バケット名/o/
ネームスペース名のハードコードを避けるために、置換文字列G_NAMESPACEとしてネームスペース名を設定します。
事前承認リクエストの発行
画像をアップロードするときはクリデンシャルを指定していますが、画像を表示する(ダウンロードする)ときはクリデンシャルを指定する方法がありません。バケットの可視性をプライベートにした上で画像をダウンロードするために、事前承認リクエストを発行します。
事前承認リクエストのパスを保存するアプリケーション・アイテムG_PREAUTH_URLを作成します。
名前はG_PREAUTH_URL、有効範囲はアプリケーション、セキュリティのセッション・ステート保護は一番厳しい制限付き - ブラウザからの設定不可を選びます。
このアプリケーション・アイテムに値を設定するアプリケーション・アイテムの計算を作成します。
事前承認リクエストのURLを取得するために、オブジェクト・ストレージのREST APIを呼び出します。
計算アイテムとしてG_PREAUTH_URLを選択します。頻度の計算ポイントは認証後を選択します。計算タイプはファンクション本体、計算として上記のコードを記述します。
対話モード・レポートのソース変更
対話モード・レポートのソースのSQL問合せを以下のSELECT文に変更します。
select
ID
, TITLE
-- , CONTENT
, replace(CONTENT, :G_OBJECT_STORAGE_URL, :G_PREAUTH_URL) content
, AUTHOR
, PUBLISHED
, CREATED
, CREATED_BY
, UPDATED
, UPDATED_BY
from RTE_DOCUMENTS
以前はapex_session=の引数を画像URLに付加し、APEXセッションでORDSへのGETリクエストの認証を通していました。この部分を、事前承認済リクエストのURLに置き換えています。
editingDowncastコンバーターの変更
CKEditor5内で画像を表示するときは、editingDowncastコンバーターを構成し、画像URLを見つけてapex_session引数を追加していました。今回はその代わりに、見つけた画像URLを事前承認済リクエストのURLに置き換えています。
ページ・アイテムP2_CONTENTの詳細のJavaScript初期化コードを入れ替えます。
画像の紐付けの変更
ドキュメントに含まれるイメージの参照先が、G_IMAGE_URLからG_OBJECT_STORAGE_URLに変更されています。文書と画像を紐づけているプロセス画像の紐付けのPL/SQLコードを以下に変更します。
外部キー制約の変更
表RTE_IMAGESには外部キー制約RTE_IMAGES_DOCUMENT_ID_FKが設定されていて、親である表RTE_DOCUMENTSから文書が削除されると、CASCADE設定により含まれる画像も削除されるようになっていました。オブジェクト・ストレージに保存した画像は自動的には保存されないため、CASCADEからON DELETE SET NULLに変更します。
alter table "RTE_IMAGES" drop constraint "RTE_IMAGES_DOCUMENT_ID_FK";
alter table "RTE_IMAGES" add constraint "RTE_IMAGES_DOCUMENT_ID_FK"
foreign key ("DOCUMENT_ID") references "RTE_DOCUMENTS" ("ID") on delete set null;
表RTE_IMAGESの列DOCUMENT_IDがNULLの画像は、親となる文書が存在していません。定期的なハウスキーピングのジョブにて、行の削除と同時にオブジェクト・ストレージ上の画像の削除を行なうようにするよ良いでしょう。
以上でCKEditor5による画像のアップロード先/ダウンロード先をオブジェクト・ストレージに変更できました。
今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/ORDS_REST_WKSP_APEXDEV_rteditor_2023_07_04_2.sql
https://github.com/ujnak/apexapps/blob/master/exports/ckeditor-image-sample-obs.zip
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完