Oracle APEXでOCI ObjectStorageに日本語ファイル名のファイルを置く(後編)
前編の続きとなります。
前編ではOracle APEXのインスタンス作成、ワークスペース作成、オブジェクトストレージのバケットとポリシーなどの設定を行いました。
後編では実際にOracle APEXのアプリを作って、アップロードするページとオブジェクトストレージ内のファイル一覧を表示するページを作っていきます。
アプリケーションの作成
アップロード用のアプリケーションを作っていきます。
- Oracle APEXのワークスペースにログインします。
- 「アプリケーションビルダー」 -> 「作成」 -> 「新規アプリケーション」 を選びます。
- アプリケーション名を適当に入力し、「アプリケーションの作成」を押します。
- アプリケーションが作成されると、3ページだけ作られた状態で出来上がります。
アップロードページの作成
- 「ページの作成」 -> 「空白ページ」 と選びます。
- ページ番号は100、名前はUploadFilesとしておきます。「次」を2回押します。
- ページが作成されます。下のパーツ一覧から「静的コンテンツ」を選び、「Content Body」に貼り付けます。
- さらに「ファイル参照」と「ボタン(Text)」を静的コンテンツリージョン内に配置します。
- 「ファイル参照」を選び、プロパティを下記のように変更します。
Key | Value |
---|---|
名前 | P100_FILES |
ラベル | ファイルアップロード |
表示形式 | Inline Dropzone |
記憶域タイプ | Table APEX_APPLICATION_TEMP_FILES |
ファイルをパージするタイミング | End Of Request |
複数ファイルの許可 | オン |
- 次にボタンを押したときの動作を指定します。
- ボタンの名前を「P100_UPLOAD」、ラベルを「アップロード」にします。
- ボタンのプロパティにある「アクション」が「送信」になっていることを確認します。
- これでこのボタンを押したときに、ファイルがAPEX_APPLICATION_TEMP_FILESテーブルに格納されます。そしてそのうち消されます。
- APEX_APPLICATION_TEMP_FILESテーブルにあるデータをオブジェクトストレージにアップロードする処理を「プロセス」を使って記述します。
- 画面左上にループ矢印のアイコンがありますので、選びます。
- 「送信後」を右クリックし、「プロセスの作成」を選びます。
Key | Value |
---|---|
名前 | UploadFileToObjectStorage |
タイプ | コードを実行 |
ソース:位置 | ローカル・データベース |
言語 | PL/SQL |
PL/SQLコード | (後述) |
成功メッセージ | アップロード完了しました |
エラーメッセージ | 失敗しました |
タイプ | 行が返される |
SQL問い合わせ | select * from apex_application_temp_files |
-
「サーバー側条件」に「SQL問い合わせ」で条件を指定していますので、ページの送信後にapex_application_temp_filesテーブルにデータがあればUploadFileToObjectStorageが呼び出されるようになります。
-
PL/SQLコードは下記の通りです。日本語ファイル名に対応するため、UTL_URLのESCAPE関数を使っています。
-
DBMS_CLOUD.PUT_OBJECTの説明にはfile_nameパラメータが必要、と書いてありますが、サンプルコードにはfile_nameパラメータがなかったので省略しています。
declare
l_request_url varchar2(4096);
l_bucket_url varchar2(2048);
l_encoded_filename varchar2(512);
begin
--ファイルアップロード
for file in (
select * from apex_application_temp_files
) loop
l_encoded_filename:=UTL_URL.ESCAPE (file.filename,true,'UTF-8');
l_bucket_url := :G_BUCKET_URL;
l_request_url :=l_bucket_url || l_encoded_filename;
DBMS_CLOUD.PUT_OBJECT(
credential_name=>:G_BUCKET_CRED,
contents =>file.blob_content,
object_uri=>l_request_url
);
end loop;
end;
- これでアップロード部分が出来ました。ファイルをアップロードしてオブジェクトストレージのバケット内を確認してみてください。
ファイル一覧とダウンロード機能を追加
アップロード機能ができたので、アップロードされているファイルの一覧と、ダウンロード機能を追加しましょう。
- ファイルアップロードリージョンの下に、「クラシック・レポート」リージョンを追加します。
- プロパティの「SQL問い合わせ」に、下記SQL文を入れて保存します。
select * from DBMS_CLOUD.LIST_OBJECTS(
credential_name =>:G_BUCKET_CRED,
location_uri =>:G_BUCKET_URL
);
- 下記画像のような感じで、オブジェクトストレージに保管されているファイルが表示されると思います。SQL書くだけで表作ってくれるので便利ですね。
-
Checksum列とCreated列は表示しなくても良いので、エディタ画面に戻って「非表示列」に変更します。
-
ファイル名をクリックしたときにダウンロードできるのが自然なので、OBJECT_NAME列を「プレーン・テキスト」から「リンク」に設定します。
-
一旦このページは保存して置いておきます。
-
空白ページを追加します。 ページ番号101、ページ名DownloadFile、非モーダルダイアログとします。
-
静的コンテンツを1つ貼り付け、そこにテキストフィールドを1つ貼り付けます。
-
テキストフィールドの名前はP101_OBJECT_NAMEとします。
-
エディタで開き、画面左上の「レンダリング前」->「ヘッダーの前」を選び、プロセスを追加します。
-
プロセス名は何でも良いのですが、Downloadとしておきます。
-
下記PL/SQLコードを貼り付けます。日本語ファイル名に対応するため、こちらでもESCAPE関数を使っています。
declare
l_blob BLOB := NULL;
l_request_url varchar2(4096);
BEGIN
l_request_url := :G_BUCKET_URL || UTL_URL.ESCAPE (:P101_OBJECT_NAME,true,'UTF-8');
--get data from object storage
l_blob := DBMS_CLOUD.GET_OBJECT(
credential_name => :G_BUCKET_CRED,
object_uri => l_request_url );
-- download to client
sys.htp.init;
sys.htp.p('Content-length: ' || DBMS_LOB.GETLENGTH(l_blob));
sys.htp.p('Content-Disposition: attachment; filename="'
|| :P101_OBJECT_NAME || '"' );
sys.htp.p('Cache-Control: max-age=3600'); -- if desired
sys.owa_util.http_header_close;
sys.wpg_docload.download_file(l_blob);
apex_application.stop_apex_engine;
end;
-
「ヘッダーの前」にプロセスをもう一つ追加します。タイプは「ダイアログを閉じる)にします。
-
これでこのページが呼び出された際、HTTPヘッダを返す前にプロセスが走り、指定されたファイルがダウンロードされるようになります。
-
ページ101を保存して閉じます。
-
ダウンロード用のページができたので、ファイル名のリンクを踏んだらファイル名をページ101に渡してダウンロードを実行するよう編集していきます。
-
ページ100 UploadFilesをページエディタで開きます。
-
ObjectName列をリンクに変更し、「ターゲット」ボタンを押してリンクビルダーのダイアログを出します。
-
下記のように編集します。
- これで、ファイル名のリンクを踏んだときにP101のテキストフィールドに値が入り、P101ページが呼び出され、ファイルがオブジェクトストレージからAPEXサーバ、APEXサーバからPCへダウンロードされます。
以上です。
お疲れさまでした。
Discussion