本当に久しぶりにコード書いてて浦島太郎状態なんですが、いつの間にか HttpClinet がふたつに増えてました。
- Windows.Web.Http.HttpClient を使って HTTP サーバーに接続する方法 (C#/VB/C++ と XAML を使った Windows ランタイム アプリ) (Windows)
- System.Net.Http.HttpClient を使った HTTP サーバーへの接続 (C#/VB と XAML を使った Windows ストア アプリ) (Windows)
で、使い慣れた System.Net.Http.HttpClient にはこんな注釈が...
注 System.Net.Http 名前空間と System.Net.Http.Headers 名前空間は、Windows の将来のバージョンでは Windows ストア アプリ用に使用できないことがあります。Windows 8.1 および Windows Server 2012 R2 以降、Windows ランタイム アプリでは代わりに、Windows.Web.Http 名前空間の Windows.Web.Http.HttpClient と、関連する Windows.Web.Http.Headers 名前空間および Windows.Web.Http.Filters 名前空間を使います。
それなら新しい方使えばいいよね。って思ったのですが注意点もあるようです。
@kazuakix でもWindows空間のやつって、マーシャリングはしるし遅そう…
— ゆたか (@tmyt) 2014, 5月 17
「Content-Type : text/xml」のようにcharset指定がないとASCII文字が返ってくるので、文字化けが発生したような状態になります。この問題を回避するには、サーバー側でhttpヘッダーにcharsetを返すようにするか、取得したデータから正しいエンコーディングで処理しないといけません。
使い方も地味~に違ってます。
System.Net.Http のつもりでこんな感じで書きかけたのですが、
var req = new HttpClient(); var res = await req.GetAsync(uri); if (res.IsSuccessStatusCode) { var folder = await Windows.Storage.KnownFolders.PicturesLibrary.CreateFolderAsync("FlashAir", CreationCollisionOption.OpenIfExists); if (null == folder) return false; var file = await folder.CreateFileAsync(FileName, CreationCollisionOption.ReplaceExisting); using (var src = await res.Content.ReadAsStreamAsync()) using (var dst = await file.OpenStreamForWriteAsync()) { byte[] buffer = new byte[src.Length]; src.Read(buffer, 0, (int)src.Length); dst.Write(buffer, 0, (int)src.Length); } return true; }
こんな感じでしょうか?
using (var src = (await res.Content.ReadAsInputStreamAsync()).AsStreamForRead()) using (var dst = await file.OpenStreamForWriteAsync()) { byte[] buffer = new byte[(int)res.Content.Headers.ContentLength]; src.Read(buffer, 0, (int)res.Content.Headers.ContentLength); dst.Write(buffer, 0, (int)res.Content.Headers.ContentLength); }
HttpResponseMessage.Content が HttpContent から IHttpContent になってるからなのか ReadAsStreamAsync がありませんでした。ReadAsInputStreamAsync したものを AsStreamForRead ... ってなんか面倒になってますね。
他にも取得した stream に Length プロパティがなかったので レスポンス ヘッダ の ContentLength を見るようにしました。
これで遅いようなら System.Net.Http に戻すと思います。