本日は HoloLens の調査枠です。
前回記事の続きです。
bluebirdofoz.hatenablog.com
今回はPOSTメッセージを使って HoloLens の特定のディレクトリにファイルをアップロードしてみます。
なお、HoloLens で利用可能な API は以下の公式ページにまとめられています。
・デバイス ポータル コア API リファレンス(すべての Windows 10 デバイスに共通する API)
docs.microsoft.com
・デバイス ポータル Mixed Reality API リファレンス(HoloLens で利用できるすべての REST API の拡張リスト)
docs.microsoft.com
サンプルコード
HoloLens の特定のディレクトリにファイルをアップロードするサンプルコードを作成します。
ファイルアクセスの API は以下の /api/filesystem/apps/file です。
ファイルをアップロードする場合、POSTメッセージを利用します。
ただし、ブラウザを介さないWifi接続を利用する場合はSSLを無効にしないとPOSTが失敗するようです。
DevicePortalから Preferences -> SSLconnection -> required のチェックを外しておきます。
ローカルフォルダにある upload.jpg を、HoloLens の Picuture フォルダにアップロードするサンプルコードを作成してみました。
以下の通り、Program.cs を修正しました。
・Program.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; // HttpClient を利用するための追加 using System.Net.Http; namespace HoloLensAPIConsole { class Program { static void Main(string[] args) { // 実行例 "HoloLensAPIConsole.exe D:\WORK\HoloLensAPITest\Upload\UploadImage.jpg" // アップロードするファイルパスは引数で指定する if (args.Length == 1) { // 1つ目の引数をファイルパスとして取得する string uploadFilePath = args[0]; // ファイルの取得処理を呼び出す HttpHoloAccess access = new HttpHoloAccess(); access.PostFile(uploadFilePath); } return; } /// <summary> /// HoloLensのRestAPIへのアクセスクラス /// </summary> class HttpHoloAccess { // HoloLensの接続設定 // IPアドレス、ユーザー名、パスワード string Target_ipaddress { get; } string Target_username { get; } string Target_password { get; } /// <summary> /// インスタンス生成(指定無し) /// </summary> public HttpHoloAccess() { // 指定がなければデフォルト設定を利用する Target_ipaddress = "127.0.0.1:10080"; Target_username = "USERNAME"; Target_password = "PASSWORD"; } /// <summary> /// インスタンス生成(接続先設定あり) /// </summary> /// <param name="a_ipaddress">HoloLesnのIPアドレス</param> /// <param name="a_username">DevicePortalのユーザー名</param> /// <param name="a_password">DevicePortalのパスワード</param> public HttpHoloAccess(string a_ipaddress, string a_username, string a_password) { // 接続先の指定があれば設定を行う Target_ipaddress = a_ipaddress; Target_username = a_username; Target_password = a_password; } /// <summary> /// ファイルのアップロード関数 /// (Picturesフォルダ直下のファイルをアップロードする) /// </summary> /// <param name="a_UploadFilePath">アップロードファイルパス</param> public void PostFile(string a_UploadFilePath) { // 利用するAPIを指定(ファイル取得)してURLを作成する string api = "/api/filesystem/apps/file"; string url = "http://" + Target_ipaddress + api; // リクエストに設定するパラメータを指定する Dictionary<string, string> parameters = new Dictionary<string, string>() { { "knownfolderid", "Pictures" }, { "packagefullname", "\\\\" }, { "path", "\\\\" } }; // Http アクセスに HttpClient を利用する HttpClient client = new HttpClient(); // アップロードするファイルコンテンツを取得する MultipartFormDataContent content = new MultipartFormDataContent(); StreamContent fileContent = new StreamContent(System.IO.File.OpenRead(a_UploadFilePath)); // ファイル名を取得する string filename = System.IO.Path.GetFileName(a_UploadFilePath); // コンテンツ情報を追加したヘッダーを作成する // 以下のコードを使うと文字化けする //fileContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") //{ // Name = System.IO.Path.GetFileName(uploadFilepath), // FileName = System.IO.Path.GetFileName(uploadFilepath) //}; // https://qiita.com/kawaidainfinity/items/4aee443bd77a9888cc9c を参考に手動エンコード string headerValue = string.Format("form-data; name=\"{0}\"; filename=\"{1}\"", filename, filename); byte[] headerValueByteArray = Encoding.UTF8.GetBytes(headerValue); StringBuilder encodingHeaderVaule = new StringBuilder(); foreach (byte b in headerValueByteArray) { encodingHeaderVaule.Append((char)b); } fileContent.Headers.Add("Content-Disposition", encodingHeaderVaule.ToString()); content.Add(fileContent); // URLを作成する string urlRequest = string.Format("{0}?{1}", url, new FormUrlEncodedContent(parameters).ReadAsStringAsync().Result); // POSTメソッドのリクエストメッセージを作成 HttpRequestMessage request = new HttpRequestMessage { Method = HttpMethod.Post, RequestUri = new Uri(urlRequest), Content = content }; // ヘッダに Basic 認証を設定 // ユーザー名とパスワードを指定 request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue ( "Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", Target_username, Target_password))) ); // リクエストの実行 HttpResponseMessage response = client.SendAsync(request).Result; // レスポンスコードを表示 // リクエスト成功時は OK (200=正常)が表示される LogMessage(response.StatusCode.ToString()); LogMessage(response.ToString()); } /// <summary> /// ログメッセージの処理関数 /// </summary> /// <param name="message">ログメッセージ</param> private void LogMessage(string message) { // ログメッセージはコンソールに表示する System.Diagnostics.Trace.WriteLine(message); Console.WriteLine(message); } } } }
アクセスする HoloLens に合わせて以下の変数は変更してください。
target_ipaddress = "127.0.0.1:10080"; target_username = "USERNAME"; target_password = "PASSWORD";
127.0.0.1:10080 のアドレス(USB接続)で HoloLens にアクセスする方法は以下を参照ください。
bluebirdofoz.hatenablog.com
本プログラムは引数で、アップロードするファイルのパスを指定します。
VisualStudio 上で動作させる場合は以下の手順で、実行時の引数を指定します。
メニューから デバッグ -> HoloLensAPIConsoleのプロパティ を選択します。
プロパティ画面が開くので、[デバッグ]タブを選択します。
[開始オプション]の[コマンドライン引数]に、実行時の引数を書き込みます。
アップロードするファイルパスはコンソールアプリを実行するローカルPCのファイルパスを指定します。
これで引数の設定は完了です。
メニューから デバッグ -> デバッグなしで開始 を選択して処理を実行します。
コンソールが開き、プログラムが実行されます。
処理が成功すれば「OK」の文字がコンソールに出力されます。
HoloLens の Pictures ディレクトリを確認すると、ファイルがアップロードされています。