WebRequestクラスとWebResponseクラスを使って、指定されたURL(URI)のデータを取得する方法を紹介します。
「ファイルをダウンロードし保存する」や「ファイルをダウンロードし表示する」で紹介しているWebClientクラスも内部ではWebRequest、WebResponseクラスを使用しています。よって、WebClientクラスだけではできないようなことも、ここで紹介している方法ならできるかもしれません。
早速ですが、具体例を示します。次の例では、「http://www.microsoft.com」からデータをダウンロードして、HTMLソースを表示しています。
'HttpWebRequestを作成 Dim webreq As System.Net.HttpWebRequest = _ DirectCast(System.Net.WebRequest.Create("http://www.microsoft.com"), _ System.Net.HttpWebRequest) 'または、 'Dim webreq As System.Net.WebRequest = _ ' System.Net.WebRequest.Create("http://www.microsoft.com") 'サーバーからの応答を受信するためのHttpWebResponseを取得 Dim webres As System.Net.HttpWebResponse = _ DirectCast(webreq.GetResponse(), System.Net.HttpWebResponse) 'または、 'Dim webres As System.Net.WebResponse = webreq.GetResponse() '応答データを受信するためのStreamを取得 Dim st As System.IO.Stream = webres.GetResponseStream() '文字コードを指定して、StreamReaderを作成 Dim sr As New System.IO.StreamReader(st, System.Text.Encoding.UTF8) 'データをすべて受信 Dim htmlSource As String = sr.ReadToEnd() '閉じる sr.Close() st.Close() webres.Close() '「st.Close()」や「webres.Close()」だけでもよい '取得したソースを表示する Console.WriteLine(htmlSource)
//HttpWebRequestを作成 System.Net.HttpWebRequest webreq = (System.Net.HttpWebRequest) System.Net.WebRequest.Create("http://www.microsoft.com"); //または、 //System.Net.WebRequest webreq = // System.Net.WebRequest.Create("http://www.microsoft.com"); //サーバーからの応答を受信するためのHttpWebResponseを取得 System.Net.HttpWebResponse webres = (System.Net.HttpWebResponse)webreq.GetResponse(); //または、 //System.Net.WebResponse webres = webreq.GetResponse(); //応答データを受信するためのStreamを取得 System.IO.Stream st = webres.GetResponseStream(); //文字コードを指定して、StreamReaderを作成 System.IO.StreamReader sr = new System.IO.StreamReader(st, System.Text.Encoding.UTF8); //データをすべて受信 string htmlSource = sr.ReadToEnd(); //閉じる sr.Close(); st.Close(); webres.Close(); //「st.Close()」や「webres.Close()」だけでもよい //取得したソースを表示する Console.WriteLine(htmlSource);
この例では取得するHTMLソースの文字コードがUTF-8のため「Encoding.UTF8」を使用していますが、別の文字コードの場合は別のEncodingオブジェクトを使用する必要があります。詳しくは、「目的の文字コードに合ったEncodingオブジェクトを取得する」をご覧ください。
補足:StreamReaderが使用するエンコーディングはデフォルトでUTF-8ですので、上記の例では「Encoding.UTF8」を省略できます。
WebRequestインスタンスは、WebRequest.Createメソッドで作成します。この時、指定されたURIによって、適切なWebRequestクラスの派生クラスが返されます。例えば、上記のようにURIのスキームがhttp://またはhttps://の場合は、HttpWebRequestクラスのインスタンスを返します。また、file://の場合は、FileWebRequestクラスを返します。さらに、.NET Framework 2.0以降では、ftp://の場合、FtpWebRequestクラスを返します。
補足:上記の例ではURIのスキームがhttp://のため、WebRequest.Createメソッドが返すインスタンスをHttpWebRequest型にキャストしていますが、file://やftp://の場合は、FileWebRequestやFtpWebRequestにキャストする必要があります(またはコメントのように、WebRequest型として取得します)。「HttpWebResponse」も同様です。
上記の方法は同期処理のため、受信が完了するまでの間、フリーズしたようになります。これを解決するには、スレッド化するか、非同期処理を行います。ここでは非同期処理の方法について、具体的な例を紹介します。
非同期処理では、まずWebRequest.BeginGetResponseメソッドにより、サーバーからの応答を要求し、待機します。さらに、データを非同期で受信するために、Stream.BeginReadメソッドで読み込みを開始します。
次に示すコンソールアプリケーションのサンプルでは、非同期で「http://www.microsoft.com」からデータを受信し、表示しています。
なおこのような非同期処理では、マルチスレッドプログラミングの知識がある程度必要になります。マルチスレッドプログラミングについては、「.NETのマルチスレッドプログラミング」を参考にしてください。
Class MainClass '受信した全データを入れておくMemoryStream Private Shared requestData As System.IO.MemoryStream '受信したデータが一時的に入るバイト型配列 Private Shared bufferData As Byte() 'エントリポイント Public Shared Sub Main() 'HttpWebRequestを作成 Dim webreq As System.Net.HttpWebRequest = DirectCast( _ System.Net.WebRequest.Create("http://www.microsoft.com"), _ System.Net.HttpWebRequest) '非同期要求を開始 '状態オブジェクトとしてHttpWebRequestを渡す Dim r As IAsyncResult = DirectCast( _ webreq.BeginGetResponse( _ New AsyncCallback(AddressOf ResponseCallback), webreq), _ IAsyncResult) 'アプリケーションが終わらないように待機する Console.ReadLine() End Sub '非同期要求が終了した時に呼び出されるコールバックメソッド Private Shared Sub ResponseCallback(ar As IAsyncResult) '状態オブジェクトとして渡されたHttpWebRequestを取得 Dim webreq As System.Net.HttpWebRequest = _ DirectCast(ar.AsyncState, System.Net.HttpWebRequest) '非同期要求を終了 Dim webres As System.Net.HttpWebResponse = _ DirectCast(webreq.EndGetResponse(ar), System.Net.HttpWebResponse) 'データを読み込むためのストリームを取得 Dim st As System.IO.Stream = webres.GetResponseStream() 'データを読み込むための準備をする requestData = New System.IO.MemoryStream() bufferData = New Byte(1023) {} '非同期でデータの読み込みを開始 '状態オブジェクトとしてStreamを渡す Dim r As IAsyncResult = DirectCast( _ st.BeginRead(bufferData, 0, bufferData.Length, _ New AsyncCallback(AddressOf ReadCallback), st), _ IAsyncResult) End Sub '非同期読み込み完了時に呼び出されるコールバックメソッド Private Shared Sub ReadCallback(ar As IAsyncResult) '状態オブジェクトとして渡されたStreamを取得 Dim st As System.IO.Stream = _ DirectCast(ar.AsyncState, System.IO.Stream) 'データを読み込む Dim readSize As Integer = st.EndRead(ar) 'データが読み込めたか調べる If readSize > 0 Then 'データが読み込めた時 '読み込んだデータをMemoryStreamに保存する requestData.Write(bufferData, 0, readSize) Console.WriteLine("{0}バイト 読み込み完了", requestData.Length) '再び非同期でデータを読み込む Dim r As IAsyncResult = DirectCast( _ st.BeginRead(bufferData, 0, bufferData.Length, _ New AsyncCallback(AddressOf ReadCallback), st), _ IAsyncResult) Else 'データの読み込みが終了した時 'ダウンロードしたデータをバイト型配列に変換 Dim sourceData As Byte() = requestData.ToArray() 'データを文字列に変換 Dim sourceHtml As String = _ System.Text.Encoding.UTF8.GetString(sourceData) '結果を表示する Console.Write(sourceHtml) '閉じる st.Close() requestData.Close() End If End Sub End Class
using System; class MainClass { //受信した全データを入れておくMemoryStream private static System.IO.MemoryStream requestData; //受信したデータが一時的に入るバイト型配列 private static byte[] bufferData; //エントリポイント public static void Main() { //HttpWebRequestを作成 System.Net.HttpWebRequest webreq = (System.Net.HttpWebRequest) System.Net.WebRequest.Create("http://www.microsoft.com"); //非同期要求を開始 //状態オブジェクトとしてHttpWebRequestを渡す IAsyncResult r = (IAsyncResult)webreq.BeginGetResponse( new AsyncCallback(ResponseCallback), webreq); //アプリケーションが終わらないように待機する Console.ReadLine(); } //非同期要求が終了した時に呼び出されるコールバックメソッド private static void ResponseCallback(IAsyncResult ar) { //状態オブジェクトとして渡されたHttpWebRequestを取得 System.Net.HttpWebRequest webreq = (System.Net.HttpWebRequest)ar.AsyncState; //非同期要求を終了 System.Net.HttpWebResponse webres = (System.Net.HttpWebResponse)webreq.EndGetResponse(ar); //データを読み込むためのストリームを取得 System.IO.Stream st = webres.GetResponseStream(); //データを読み込むための準備をする requestData = new System.IO.MemoryStream(); bufferData = new byte[1024]; //非同期でデータの読み込みを開始 //状態オブジェクトとしてStreamを渡す IAsyncResult r = (IAsyncResult)st.BeginRead( bufferData, 0, bufferData.Length, new AsyncCallback(ReadCallback), st); } //非同期読み込み完了時に呼び出されるコールバックメソッド private static void ReadCallback(IAsyncResult ar) { //状態オブジェクトとして渡されたStreamを取得 System.IO.Stream st = (System.IO.Stream)ar.AsyncState; //データを読み込む int readSize = st.EndRead(ar); //データが読み込めたか調べる if (readSize > 0) { //データが読み込めた時 //読み込んだデータをMemoryStreamに保存する requestData.Write(bufferData, 0, readSize); Console.WriteLine("{0}バイト 読み込み完了", requestData.Length); //再び非同期でデータを読み込む IAsyncResult r = (IAsyncResult)st.BeginRead( bufferData, 0, bufferData.Length, new AsyncCallback(ReadCallback), st); } else { //データの読み込みが終了した時 //ダウンロードしたデータをバイト型配列に変換 byte[] sourceData = requestData.ToArray(); //データを文字列に変換 string sourceHtml = System.Text.Encoding.UTF8.GetString(sourceData); //結果を表示する Console.Write(sourceHtml); //閉じる st.Close(); requestData.Close(); } } }
補足:BeginGetResponseメソッドではWebRequest.Timeoutプロパティは無視されますので、タイムアウト処理は自分で行う必要があります。MSDNの「HttpWebRequest.BeginGetResponse メソッド」にあるサンプルではタイムアウト処理がされていますので、参考になります。