ゆうなんとかさんの雑記帳的な。

Twitterで踊ったり音ゲーしたりしてるあの名前がよくわからない人が書いてるらしいよ。

バイナリファイルをダウンロードして保存するまでやってみた

用意するのはWebClientとMemoryStreamです。大まかな流れは、

  1. WebClientで普通にダウンロードする
  2. レスポンスをMemoryStreamにコピー
  3. Byteの配列にダンプしてファイルに書き込み

の3段構成です。
C#3.0からあるらしいFile.WriteAllBytesをありがたく使っています。これはファイルパスとバイト列を渡すとバイト列の中身を問答無用でファイルに上書き保存してくれるユーティリティメソッドです。今回気づいたのですが、Asyc系のメソッドを使うとTask.ContinueWithでメソッドチェーンが作れるようですね。

private static readonly object _lock = new object();

private static byte[] ReadFullStream(Stream st)
{
    lock (_lock)
    {
        var buffer = new byte[65536];
        int bytesRead;
        using (var ms = new MemoryStream())
        {
            var isFinished = false;
            while (!isFinished)
            {
                bytesRead = st.Read(buffer, 0, buffer.Length);
                if (bytesRead > 0)
                {
                    ms.Write(buffer, 0, bytesRead);
                }
                else
                {
                    isFinished = true;
                }
            }
            return ms.ToArray();
        }
    }
}

async void LoadBinary(string url, string path)
{
    var client = new WebClient();
    var task = client.OpenReadTaskAsync(url);// 手順1がここまで
    await task.ContinueWith(s => ReadFullStream(s.Result)). //手順2がここ
               ContinueWith(bytes => File.WriteAllBytes(path, bytes.result)); //手順3がここ
}

参考

asp.net - C# How do i convert System.Net.ConnectStream to a byte[] (array) - Stack Overflow
ReadFullStreamというメソッドはここをほぼ丸パクリおおいに参考にしました。