開発環境;visual studio 2015
開発言語:c#.net
1.概要
WEB上にあるファイルをフォームアプリケーションを使ってダウンロードしようと思ったのですが
方法がたくさんあって迷ってしまった。
とりあえずやりたいことは、
①バイナリ型式でダウンロードする
②非同期処理(デッドロックしないようにする)
③ダウンロード完了時にイベントを発生させる
④ダウンロードのタイムアウト時間を設ける
が今回の条件でした。
では、【WebClient】クラスを使ったと想定して1つづつ検証していきます。
2.検証内容
①バイナリ型式でダウンロードする。
なぜ、こんなことが条件になっているのかというと
ダウンロードしたデータの中身を解析する必要がありました。
これについては【DownloadDataAsync】メソッドを使うことで実現できました。
②非同期処理(デッドロックしないようにする)
同期処理にすると、ダウンロードが完了するまで
フォームアプリケーションが操作不可能になってしまうので
これを避けるために非同期処理が必要でした。
これについては【DownloadDataAsync】メソッドを使うことで実現できました。
③ダウンロード完了時にイベントを発生させる
複数のファイルを順番にダウンロードするのが目的でした。
1つのファイルがダウンロード完了したら、次のファイルといった感じで
リストの順番でしっかりダウンロードを行う。
これについては【DownloadDataCompleted】イベントハンドラを作成することで実現できました。
④ダウンロードのタイムアウト時間を設ける
これについては標準ではタイムアウトの設定が出来ないようです。
悩んだ結果、独自で【Timer】クラスを実行し、
【Timer_Tick】イベント内で【CancelAsync】を実行することで対応しました。
上記の結果から【WebClient】クラスで問題ないと判断し実装することに決めました。
以下ソースです。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Net; namespace downloadFile { public partial class Form1 : Form { //WebClientフィールド System.Net.WebClient downloadClient = null; //ダウンロードしたファイルの保存先 string fileName = "C:\\work\\1.jpg"; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { //ダウンロード基のURL Uri u = new Uri("http://www.cor-art.com/best/tenkei/down/pSA001.jpg"); //WebClientの作成 if (downloadClient == null) { downloadClient = new System.Net.WebClient(); //イベントハンドラの作成 downloadClient.DownloadDataCompleted += new System.Net.DownloadDataCompletedEventHandler(downloadClient_DownloadDataCompleted); } // ダウンロードを開始する timer1.Start(); downloadClient.DownloadDataAsync(u); } private void downloadClient_DownloadDataCompleted(object sender, System.Net.DownloadDataCompletedEventArgs e) { timer1.Stop(); if (e.Cancelled) { Console.WriteLine("処理がタイムアウトしました。"); } else if (e.Error != null) { Console.WriteLine("エラー:{0}", e.Error.Message); } else { Console.WriteLine("ダウンロードが完了しました。"); byte[] sourceData = e.Result; // sourceDataの解析処理sample(ちゃんとjpgファイルがダウンロードされているか) if (sourceData[sourceData.Length - 2] == (Byte)0xff && sourceData[sourceData.Length - 1] == (Byte)0xd9) { // FileStreamを作成 System.IO.FileStream fs = new System.IO.FileStream(fileName, System.IO.FileMode.Create, System.IO.FileAccess.Write); // 書き込み fs.Write(sourceData, 0, sourceData.Length); // 閉じる fs.Close(); }else { Console.WriteLine("jpgファイルではありません"); } } } private void timer1_Tick(object sender, EventArgs e) { timer1.Stop(); downloadClient.CancelAsync(); } } }
ソースの内容は
サンプルのjpgファイルをバイナリ型式でダウンロードして
本当にjpgファイルなのか解析し、問題なければ
【C:\work\1.jpg】
に保存しています。
【timer】で10秒のタイムアウトを設けています。