2025年3月13日木曜日

レポート上にダウンロード・ボタンを配置しZIP圧縮してコンテンツをダウンロードする

対話モード・レポート上にダウンロード・ボタンを配置し、ボタンのある行のBLOB列のコンテンツをZIP圧縮してダウンロードします。無圧縮であればレポート列の設定だけでコンテンツのダウンロードはできます。今回はZIP圧縮するため、Oracle APEX 24.1で追加された動的アクションダウンロードを活用します。

わかりにくい例ですが、以下のように動作するAPEXアプリケーションを作成します。


最初に標準のダウンロードを実装したAPEXアプリケーションを作成します。

SQLワークショップのクイックSQLを開き、以下のモデルを元に表EBAJ_PHOTOSを作成します。
# prefix: ebaj
# pk: identity
photos
    title vc80 /nn
    photo file

画面に従ってDDLの生成と実行を行います。表が作成されたら、アプリケーションの作成を呼び出します。


作成されるアプリケーションに、デフォルトで表EBAJ_PHOTOSのフォーム付き対話モード・レポートのページが含まれます。

そのまま、アプリケーションを作成します。


アプリケーションが作成されます。

最初に対話モード・レポートのページを修正します。ページ・デザイナでページ番号2を開きます。


対話モード・レポートの列PHOTOを選択します。ページ作成ウィザードはBLOB属性の一部を設定しません。

MIMEタイプ列にPHOTO_MIMETYPE、ファイル名列にPHOTO_FILENAME、最終更新列にPHOTO_LASTUPD、文字セット列にPHOTO_CHARSETを設定します。

以上で変更を保存します。


ページ・デザイナでページ番号3のフォームのページを開き、同様の変更を行います。

ページ・アイテムP3_PHOTOを選択し、ストレージのMIMEタイプ列にPHOTO_MIMETYPE、ファイル名列にPHOTO_FILENAME、文字セット列にPHOTO_CHARSET、BLOB最終更新列にPHOTO_LASTUPDを設定します。

以上で変更を保存します。


以上で、APEXアプリケーションに標準のファイル・アップロードとダウンロードが実装されました。

作成したアプリケーションを実行し、いくつか写真をアップロードします。

対話モード・レポートには、写真をダウンロードするリンクが表示されます。標準のダウンロードは、アップロードした写真がそのままダウンロードされます。


これから、レポート上のダウンロードのリンクをボタンに変更し、写真がZIP圧縮されてダウンロードされるように機能を加えます。

ページ・デザイナで対話モード・レポートのページを開きます。

最初にダウンロード対象の写真を持つ行のIDを保持するページ・アイテムを作成します。

識別の名前はP2_ID、タイプは非表示とします。動的アクションにより値を設定するため、設定の保護された値はオフにします。セッション・ステートのストレージはリクエストごと(メモリーのみ)です。


JavaScriptから参照できるように、対話モード・レポートに静的IDとしてREPORTを設定します。


列PHOTOをボタンに変更します。

識別のタイプをプレーン・テキストに変更し、列の書式のHTML式に以下を記述します。カスタム属性data-idに行の主キー値#ID#を渡しています。

<button type="button" class="t-Button" data-id="#ID#">Download</button>

この列もJavaScriptから参照できるように、静的IDとしてCOLUMN_DOWNLOADを設定します。


ユニバーサル・テーマのリファレンスに含まれるボタン・ビルダーを使用すると、ボタンのマークアップを生成できます。

https://apex.oracle.com/pls/apex/r/apex_pm/ut/button-builder


ボタンをクリックしたときに、ページ・アイテムP2_IDに主キーの値を設定する動的アクションを作成します。

左ペインで動的アクション・ビューを開き、クリックのノードに動的アクションを作成します。

識別の名前はonClick Download on Reportとします。実行のイベント有効範囲を動的に変更し、静的コンテナ(jQueryセレクタ)に対話モード・レポートの静的IDである#REPORTを設定します。

タイミングのイベントはクリック、選択タイプにjQueryセレクタを選び、jQueryセレクタに以下を記述します。列PHOTOのセルにあるボタンを指定しています。

td[headers="COLUMN_DOWNLOAD"] button


TRUEアクションとして値の設定を実行します。

設定のタイプの設定にJavaScript式を選択し、JavaScript式として以下を記述します。クリックしたボタンのカスタム属性data-idに渡している値を参照しています。

this.triggeringElement.dataset.id

ページ・アイテムで発生する変更イベントを受けてダウンロードを実行するため、変更イベントの禁止はオフにします。値の設定先となる影響を受ける要素の選択タイプはアイテム、アイテムはP2_IDを選択します。

実行の初期化時に実行はオフです。


ページ・アイテムP2_IDに動的アクションを作成します。

識別の名前はonChange ID、タイミングのイベントは変更です。ページ・アイテムP2_IDの値が変更されたときに動的アクションが実行されます。


TRUEアクションとしてダウンロードを実行します。

設定の複数のファイルをオンにし、ダウンロードされるファイルがZIP圧縮されるようにします。ファイル名はphoto-&P2_ID..zipとします。

ダウンロードされるZIPファイルに含まれるファイルは、ソースに設定します。

SQL問合せとして以下を記述します。送信するアイテムとしてP2_IDを設定します。

select photo, photo_filename from ebaj_photos where id = :P2_ID

実行の初期化時に実行はオフにします。


以上で実装は完了です。アプリケーションを実行すると、記事に先頭にあるGIF動画のように動作します。

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

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

完