⚱️

Oracle APEXでOCI ObjectStorageに日本語ファイル名のファイルを置く(後編)

2021/05/17に公開

前編の続きとなります。
前編では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