【#PowerApps】何?SharePointドキュメントにファイルが保存できない?ならFlowの定義を書き換えてしまおう


概要

PowerAppsからカメラの画像をSharePointのドキュメントライブラリにアップロードするサンプルはよく見かけますが、AddMediaControlを利用したサンプルはまったく見かけない、もしくはカスタムコネクタ経由などのサンプルばかりでしたので、Flowのみを利用してSharePointのドキュメントライブラリにファイルをアップロードする仕組みを考えました。

完成系

きっかけは偶然

当初カメラと同じように画像などのファイルがアップロードできると考えていたのですが、実装してみるとどうもカメラコントロールとAddMediaControlからFlowに送られてくる値が違うことに気づきました。

カメラ経由

data:image/png;base64~~

こちらはBase64で来るので以下のリンクのような加工を行ってあげることで保存ができます。
https://qiita.com/r-wakatsuki/items/670f85c628ec231a5a5b

AddMediaControlを利用した場合の例)

appres://blobmanager/84ffb903062f41c0994f4d8a4462cd4a/1

おそらくこっちはBlobのパス?
そのため同じように base64ToBinary関数を利用してもエラーとなってしまいます。

「ならしょうがないから直接SQLDatabase にバイナリ型で保存してしまうか」(こちらはPowerAppsがよろしく変換してくれます。)
「でもせっかくならFlowを経由したほうが拡張性が高いかな」

と考えて以下のようなFlowを作成しました。

この状態で画像を保存できるかテストしてみたところ

UEsDBBQABgAIAAAAIQCkU8XPTgEAAAgEAAATAAgCW0Nvb~~~

「ん?取得する値が変わってる・・・これはもしや?」
というのが今回のきっかけでした。

実装

実装方法は2パターン存在します。
1つはSQLDatabaseを用いるパターン。もう1つはFlowの定義を書き換えるパターン。どちらもファイルは保存できるので、お好きなほうで実装してください。

SQLDatabaseを用いるパターン

先ほどのFlowの先にSharePointのファイルを作成を追加するだけです。
ただし、このままではSQLDatabaseにも保存されるので、そこは条件分岐で回避します

こんな感じですね。
ポイントはファイルの作成のファイルコンテンツには行の挿入で指定した値をそのまま渡してあげる点です。
SQLDatabase さえ用意できれば簡単に実装できます。

Flowの定義を書き換えるパターン

さて、本題ですが、結局のところ何が原因だったのかを探るため、FlowのJSONを見比べてみることにしました。

引数の部分の参照
こちらは最初に作ったFlowのJSONの一部

"properties": {
    "ファイルの作成_ファイルコンテンツ": {
        "type": "string",
        "format": "binary",
        "description": "ファイルのコンテンツ。",
        "x-ms-powerflows-param-ispartial": false
        }
    }

こっちは パターン1 のSQLを利用した場合

"properties": {
    "行の挿入_image": {
       "type": "string",
        "format": "byte",
        "x-ms-powerflows-param-ispartial": false
    }
}

ここで注目すべきは "format" です。
ここを書き換えてあげることでうまく動作しそうです。

まずこちらが今回書き換える対象の Flow です。
普通にPowerApps からファイルを受け取ってファイルの作成アクションを利用しているだけです。
注意点としてはSQLDatabaseのようにそのままではなく base64ToBinary関数を利用する点です。
(パターン1の場合はJSONを確認するとわかりますが、Flow がよろしくやってくれています。)

base64ToBinary(triggerBody()['ファイルの作成_ファイルコンテンツ'])

いろいろなファイルが渡せるように、ファイル名は PowerApps から受け取るようにします。

そしてこちらが書き換える Flow になります。

Get Flow は書き換えたいFlow を指定
変数とUpdate Flow の設定は以下の通りです。

変数

json(replace(string(body('Get_Flow')['properties']['definition']),'"binary"', '"byte"'))

今回は簡単に binaryとbyteを書き換えるように設定していますが、他にbinaryで値を受け取りたい場合などはもう少し replace関数 を工夫する必要はあります。

こちらを作成後、実行することで Flow の定義を書き換えることができます。

PowerAppsからはこんな感じで実行します。

CreateFileSharePointDocument.Run(UploadedImage1.Image,TextInput1 & "." & TextInput1_1)

注意点

1、すでにデータソースに書き換えるFlowが設定されている場合

そのままだと、書き換えてもうまく動作しません。(Flowの設定時に定義がすでにPowerAppsにも渡されているため。)そのため1度削除し、再度設定してください。

2、書き換える Flow を更新したくなった場合

ファイルコンテンツに設定した base64ToBinary関数がファイルコンテンツから消えているため、その部分も書き換えてください。情報更新後は 書き換え Flow を実行するのを忘れずに

なぜFlowで書き換えているのか?

「zipファイル書き換えればよくね?」
と思う方もいるかもしれませんが、なぜかインポート時にエラーでインポートができません。おそらくですが、ファイル作成日などを見ていて不正だと検知されているかもしれません。そのため、Update Flow を利用して書き換えています。

まとめ

一応パターン2で試したところ、画像、PDF、動画、Excelはドキュメントライブラリにアップロードすることができました。(他は試してませんがおそらくできるはず)
ただし、AddMediaControllの制限を超えたものはアップロードできないはずなのでご注意ください。
今回のFlowは失敗からひらめいたものなので、何でも失敗して試してみるもんだなぁと思いました。
もうSharePointのドキュメントライブラリ+PowerAppsは困らない?

補足

PowerApps に JSON 関数が追加されました。
これにより、追加したファイルは base64 に変更することが可能なので、 Flow の定義を書き換える必要はなくなりました。