本記事はPower Apps Advent Calendar 2024 シリーズ2の5日目担当記事になります。
後日会社HP上の技術ブログでもアップさせていただく予定ですので、その際は記事内にリンクを追記させていただきます。
はじめに
こんにちは、reireです。
皆さん、Power Appsでファイルアップロード機能を実装したことはありますか?
Power Appsでファイルのアップロードなどの機能を実装する場合は、基本的に添付ファイルコントロールを使用することになると思います。
しかし残念ながら、添付ファイルコントロールにはアップロードしたファイルのファイルサイズを取得する機能がありません。
この仕様は意外な落とし穴で、実際にファイルアップロード処理のあるアプリを構築していると、
- アップロード先のストレージに容量の制限があり、アップロード処理を実行する前にPower Apps上でファイルの合計サイズを確認できるようにしたい
- 大容量ファイルのアップロードにより待機時間が長くなってしまったり、タイムアウトが発生してしまう事態を避けたい
といった要件が出てくることは少なくありません。
そこで今回は、添付ファイルコントロールにアップロードしたファイルのそれぞれの容量を取得する方法についてご紹介したいと思います。
動作イメージ
以下のような動作をイメージしています。
今回ご紹介する方法は正確なファイルサイズの取得を保証するものではございません。
また、Power AppsやMicrosoftで公式的に推奨されているものではない点にもご注意ください。
添付ファイルコントロールとは
添付ファイルコントロールを使用したことのない方向けに、軽くおさらいしていきます。
※既にご存じの方は読み飛ばし頂ければと思います。
まず添付ファイルコントロールは挿入タブのコントロール一覧から直接アプリに追加することができません。
ではどこから追加するのかというと、編集フォームコントロールから行います。
編集フォームコントロールをアプリに追加してデータソースを指定すると、データソースの項目に応じて様々なコントロールが自動で生成されます。
その中の添付ファイルの項目に、添付ファイルコントロールが存在します。
つまり添付ファイルコントロールをアプリに追加する際は、一度編集フォームをアプリに追加して、
そこから添付ファイルコントロールをコピー&ペーストで抜き出すことになります。
そして、実際にアップロードしたファイルの情報は「Attachments」プロパティから取得することができます。
更にAttachmentsプロパティはテーブル構造となっており、格納されている情報は次の2つになります。
- Attachments.Name
- アップロードしたファイルのファイル名
- Attachments.Value
- アップロードしたファイルのBlobパス(URIテキスト)
Blobというのは、Azure Blob StorageというAzureが提供しているクラウドストレージサービスのことで、
添付ファイルコントロールからアップロードしたファイルは、一時的にBlobのストレージに保存され、Attachments.Valueにはそのパスが格納されています。
その他に設定できる主要なプロパティとしては以下の通りです。
- MaxAttachments
- 添付できるファイルの最大の数
- MaxAttachmentSize
- 添付できるファイルの最大のサイズ
- OnAddFile
- ファイルを追加したときに実行される動作
- OnRemoveFile
- ファイルを削除したときに実行される動作
ここで注意すべき点として、
MaxAttachmentSizeで指定されるファイルの最大サイズは、ファイル単体のサイズになります。
そのため、MaxAttachmentSizeに10MBを指定した場合それぞれのファイルが10MB以下であることは分かりますが、それぞれの詳細なファイルサイズや合計のファイルサイズについては取得することができません。
これでは個々や合計ファイルサイズによる制御ができないため、例えばファイルサイズが大きすぎて保存先になるデータソースで受け入れることができない、もしくはPowerAutomateのアップロード処理に時間がかかりすぎてしまうなどの問題が考えられます。
添付ファイルコントロールからファイルサイズを取得する方法
それでは実際にファイルサイズを取得する方法について解説していきます。
-
コントロールの配置
最初に添付ファイルコントロールとギャラリーを配置します。
配置したギャラリーにはラベル2つと画像を格納しましょう。
-
ファイルサイズ取得処理の実装
本題のファイルサイズ取得を実装していきます。
まずはアップロードしたファイルたちをコレクションに格納していく処理です。FileUploader.OnAddFile//アップロードされたファイルの情報をcolFilesに格納する ForAll( FileUploader.Attachments As addFile, Collect( colFiles, { Name:addFile.Name, //ファイル名 Content:addFile.Value, //blobのパス Size:0 //ファイルサイズを格納する列(現時点では0としておく) } ) ); //添付ファイルコントロールのリセット Reset(FileUploader);
ここではアップロードしたファイルをcolFilesというコレクション変数に格納しています。
ColFileに格納する値としては以下の通りです。
- Name:ファイルの名前
- Content:ファイルのBlobパス
- Size:ファイルのサイズ(現時点では0)
次に、1.で配置したギャラリーのItemsや子コントロールを設定しましょう。
galFileLists.ItemscolFiles
lblFileName.TextThisItem.Name
lblFileSize.Text"ファイルサイズ:" & ThisItem.Size
imgFileContent.ImageThisItem.Content
これでアップロードしたファイルの情報がギャラリーで表示されます。
ここまでくればもう少しです。再度添付ファイルコントロールのOnAddFileに戻り、以下の式を追加します。
FileUploader.OnAddFile//ファイルサイズを取得してcolFilesのSize列に格納 ForAll( galFileLists.AllItems As File, //galFileListsのアイテムをソースにForAllを実行 If( File.Size = 0, //ファイルサイズを取得済みのアイテムについては処理を行わない //colFilesのSize列を更新する Patch( colFiles, //colFilesとgalFileListsのアイテムをblobパスで突合 LookUp( colFiles, ThisRecord.Content = File.Content ), With( { //取得したBase64形式のテキストから不要な文字列を取り除く Base64:Substitute(Substitute(Match(JSON(File.imgFileContent.Image,JSONFormat.IncludeBinaryData),"(?<=base64,).*").FullMatch,"""",""),"=","") }, { //不要な文字列を取り除いたBase64テキストの文字数をカウントし6/8倍する Size:Len(Base64)*6/8 } ) ) ) );
ここでは先ほど作成したcolFilesコレクションに対し、ファイルサイズを計算しPatch関数でsize列の更新を行っています。
ポイントは3つになります。- 対象ファイルのBase64テキストの取得
Power Automateなどと連携してファイルのアップロード処理を実装したことのある方はご存じかもしれませんが、添付ファイルコントロールのValueを画像コントロールのImageに適用しJson関数で変換することで、ファイルデータをBase64形式で取得することができます。 - バイナリーデータとファイルサイズの関係
コンピュータ上においてファイルはバイナリーデータで扱われます。
このバイナリーデータというのはつまるところ2進数のデータなのですが、ファイルサイズとはこのバイナリーデータの量を表したものになります。
※ここで解説しているファイルサイズは、Windows上などでファイルを扱う際に付随するメタデータ(ファイル名や作成者情報など)を除いた純粋なデータサイズを指します。 - Base64とバイナリーデータの関係
Base64とはバイナリーデータをテキスト形式にエンコードする方式です。
これはバイナリーデータを扱えない環境において、テキスト形式に変換することでデータを安全に保持するための技術なのですが、ポイントは変換したときのデータ量の変化です。
詳細な解説は省きますが、Base64ではバイナリーデータを6bitごとに変換するため、元のバイナリーデータ量から8/6倍(約33%)増加します。
上記の3点をまとめると、
$$
ファイルサイズ = バイナリーデータ量 = Base64形式の文字量\times6\div8
$$
という式が成り立ちます。
つまり、- JSON(File.FileImage.Image,JSONFormat.IncludeBinaryData)でファイルデータをBase64形式で取得する。
- Json関数で取得したBase64形式のテキストには冒頭に「data:~/~;base64,」といった文字列やダブルクォーテーション、イコールなど、不要な文字列が含まれていることがあるため、Match関数の正規表現やSubstitute関数を使用し、不要な文字列を除く。
- 取得したBase64形式のテキストに対してLen関数を使用し文字数を取得し、結果を6/8倍する。
以上の手順を踏むことで、元のファイルデータのおおよその値を求めることができます。
動作確認
動作を確認してみましょう!
今回はこちらのPDFをサンプルとして使用してみたいと思います。
添付ファイルコントロールからアップロードすると…
このようにファイルサイズを取得できます!
もちろんPDFだけではなく、xlsxなどオフィス系のファイルや画像ファイルなども取得することができます!
また、上記のアプリではファイルサイズをBytes単位で表示していますが、単位をKB、MBと大きくすることも可能です。
その場合はBytes→KB→MBと単位を大きくするごとに1024で割っていくことになります。
※厳密な説明は省きますが、Windows上では1KB = 1024Bytesという計算になります。
"ファイルサイズ:" & Text(ThisItem.Size/1024/1024,"0.0") & " MB"
そして、アップロードしたファイルの合計サイズはSum関数を使用することで求めることができます。
"合計 " & Text(Sum(colFiles,Size)/1024/1024,"0.0") & " MB"
このようにしてファイルサイズの合計値を求めることで、
アップロードするファイルのサイズが大きすぎないかをPower Apps内で事前にチェックすることができますね!
おわり
以上がPower Apps上にアップロードしたファイルのファイルサイズを取得する方法でした。
添付ファイルコントロール自体には標準でサポートされていないファイルサイズの取得ですが、
ファイルサイズやデータ形式の関係をもとに計算を行うことで概ねの値を求めることが可能です。
これによりアップロードを行いたいファイルのサイズが適切な範囲かをPower Apps上で確認することができますので、
想定外の動作や不要なエラーを避け、システムの安全性を向上させることが可能になります。
なお、以下の一般的なファイルの種類についてはファイルサイズ取得の動作を確認しております。
- Word
- Excel
- Power Point
- txt
- csv
- Zip
- mp3
- mp4
再三の注意とはなりますが、
- Power AppsやMicrosoft公式の手法ではない
- 確実に正確なファイルサイズを求められるものではない
- ファイルの種類によっては正常に動作しない可能性がある
こういったポイントには留意いただいた上でご参考にしていただけますと幸いです。
ぜひ皆さまもPower Appsでの開発を楽しんでいただければと思います!
それでは!