2022年4月1日金曜日

表をCSV形式でダウンロードするアプリの作成

以下の手順で、表のデータをダウンロードするアプリを作成します。

  1. パーシング・スキーマから、表をひとつ選択する。
  2. 選択した表をオブジェクト・ストレージに、CSV形式でエクスポートする。DBMS_CLOUD.EXPORT_DATAを呼び出します。
  3. 出力されたオブジェクトのURLを取得する。
  4. オブジェクトのURLにリダイレクトし、ブラウザからダウンロードする。

表のエクスポート先となるバケットを作成します。

OCIのコンソールより、ストレージオブジェクト・ストレージとアーカイブ・ストレージバケットを開きます。


バケットの作成をクリックします。

バケット名はdownloadとします。それ以外はデフォルトのまま変更せず、作成を実行します。

バケットdownloadが作成されます。アクセス制御の実装を省くため、バケットdownload操作メニューを開き、可視性の編集を実行します。

可視性としてパブリックを選択します。ユーザーにこのバケットのオブジェクトのリスト表示を許可については、チェックを外します

変更の保存をクリックします。

バケットdownloadの準備は以上で完了です。

APEXのアプリケーション・ビルダーに移ります。

アプリケーション作成ウィザードを起動し、空のアプリケーションを作成します。名前表のエクスポートとします。

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

アプリケーションが作成されたら、ページ・デザイナホーム・ページを開きます。


Content Bodyにリージョンを作成します。

識別タイトル表のエクスポートタイプ静的コンテンツとします。


オブジェクト・ストレージの操作に使用するページ・アイテムを4つ、P1_REGIONP1_NAMESPACEP1_BUCKETおよびP1_CREDENTIALを作成します。すべてタイプテキスト・フィールドです。

ページ・アイテムP1_REGIONラベルリージョンとします。


ページ・アイテムP1_NAMESPACEラベルネームスペースとします。


ページ・アイテムP1_BUCKETラベルバケットとします。


ページ・アイテムP1_CREDENTIALラベルクリデンシャルとします。


すべてに値が設定されていないとオブジェクト・ストレージの操作ができないため、作成した4つのページ・アイテムを選択し、検証必須の値ONにします。


エクスポートする対象の表の選択に使用する、ページ・アイテムを作成します。

アイテムの作成を実行します。

識別名前P1_TABLE_NAMEタイプとしてポップアップLOVを選択します。ラベルエクスポートする表とします。検証必須の値ONです。

LOVタイプとしてSQL問合せを選択し、SQL問合せに以下を記述します。アプリケーションのパーシング・スキーマに含まれる表から、エクスポートする表を選択します。

select table_name from user_tables order by 1

追加値の表示OFFNULL値の表示ONとし、NULL表示値として- エクスポートする表を選択する -を記述します。


選択した表のオブジェクト・ストレージへのエクスポートと、ブラウザへのダウンロードを実行するボタンを作成します。

ボタンの作成を実行します。

識別ボタン名B_DOWNLOADラベルダウンロードとします。動作アクションはデフォルトのページの送信のままとします。


ボタンを押したときに実行されるプロセスを作成します。

左ペインでプロセス・ビューを表示し、プロセスの作成を実行します。

作成したプロセスの識別名前ダウンロードとします。タイプコードを実行を選択します。ソース位置ローカル・データベースPL/SQLコードとして以下を記述します。

declare
l_sql varchar2(32767);
l_uid varchar2(32);
l_path varchar2(4000);
l_operation_id number;
l_status varchar2(9);
l_object_name varchar2(200);
begin
-- 取得するデータは全行、全列を対象とする。
l_sql := 'select * from ' || :P1_TABLE_NAME;
-- 一意となる識別子をフォルダにし、その下にCSVをエクスポートする。
l_uid := rawtohex(sys_guid());
-- オブジェクト・ストレージ上の出力先。
l_path := 'https://objectstorage.' || :P1_REGION || '.oraclecloud.com/n/' || :P1_NAMESPACE
|| '/b/' || :P1_BUCKET || '/o/temp/' || l_uid || '/';
-- CSVデータの出力。gzip圧縮して最大の2GBのサイズまで。
dbms_cloud.export_data(
credential_name => :P1_CREDENTIAL
, file_uri_list => l_path || :P1_TABLE_NAME
, format => json_object(
'type' value 'csv'
, 'maxfilesize' value '214783648'
, 'compression' value 'gzip'
)
, query => l_sql
, operation_id => l_operation_id
);
/*
* もしかして終了していない場合もあるので、終了ステータスがCOMPLETEDかどうか確認する。
* ただし、10回確認してもCOMPLETEDでない場合にどうするかというコードは記載していない。
* 何か記述する必要はあり。
*/
for i in 1..10
loop
select status into l_status from user_load_operations where id = l_operation_id;
if l_status = 'COMPLETED' then
exit;
end if;
dbms_session.sleep(1);
end loop;
/*
* 出力されたオブジェクト名を取得する。
* 最大サイズの2GBを超えると複数のファイルに分割されるが、それについては考慮していない。
*/
select object_name into l_object_name from dbms_cloud.list_objects(
:P1_CREDENTIAL
, l_path
) fetch first 1 rows only;
-- 出力されたオブジェクトをダウンロードする。
apex_util.redirect_url(
p_url => l_path || l_object_name
);
end;

サーバー側の条件ボタン押下時に、B_DOWNLOADを指定します。


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

アプリケーションを実行すると、先頭のGIF動画のように動作します。

出力先として指定したバケットには、以下のように一時ファイルが残ります。


ハウスキーピングのタスクなどは、要件に応じて実装を行う必要があるでしょう。

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

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