DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

WebRequest、WebResponseクラスを使ってファイルをダウンロードし表示する

WebRequest、WebResponseクラスを使ってインターネットのデータにアクセスする方法を紹介します。こちらこちらで紹介したようなWebClientクラスでは、内部でWebRequest、WebResponseクラスを使用しています。よってここで紹介する方法を使用すれば、より柔軟で高度なことができるようになります。

次の例では、Yahoo! Japan のトップページのソースを表示しています。

VB.NET
コードを隠すコードを選択
'HttpWebRequestの作成
Dim webreq As System.Net.HttpWebRequest = _
    CType(System.Net.WebRequest.Create("http://www.yahoo.co.jp"), _
        System.Net.HttpWebRequest)
'または、
'Dim webreq As System.Net.WebRequest = _
'    System.Net.WebRequest.Create("http://www.yahoo.co.jp")

'サーバーからの応答を受信するためのHttpWebResponseを取得
Dim webres As System.Net.HttpWebResponse = _
    CType(webreq.GetResponse(), System.Net.HttpWebResponse)
'または、
'Dim webres As System.Net.WebResponse = webreq.GetResponse()

'文字コード(EUC)を指定する
Dim enc As System.Text.Encoding = _
    System.Text.Encoding.GetEncoding("euc-jp")
'応答データを受信するためのStreamを取得
Dim st As System.IO.Stream = webres.GetResponseStream()
Dim sr As New System.IO.StreamReader(st, enc)
'受信して表示
Dim html As String = sr.ReadToEnd()
Console.WriteLine(html)

'閉じる
'webres.Close()でもよい
sr.Close()
C#
コードを隠すコードを選択
//HttpWebRequestの作成
System.Net.HttpWebRequest webreq =
    (System.Net.HttpWebRequest)
        System.Net.WebRequest.Create("http://www.yahoo.co.jp");
//または、
//System.Net.WebRequest webreq =
//    System.Net.WebRequest.Create("http://www.yahoo.co.jp");

//サーバーからの応答を受信するためのHttpWebResponseを取得
System.Net.HttpWebResponse webres =
    (System.Net.HttpWebResponse) webreq.GetResponse();
//または、
//System.Net.WebResponse webres = webreq.GetResponse();

//文字コード(EUC)を指定する
System.Text.Encoding enc =
    System.Text.Encoding.GetEncoding("euc-jp");
//応答データを受信するためのStreamを取得
System.IO.Stream st = webres.GetResponseStream();
System.IO.StreamReader sr = new System.IO.StreamReader(st, enc);
//受信して表示
string html = sr.ReadToEnd();
Console.WriteLine(html);

//閉じる
//webres.Close()でもよい
sr.Close();
補足:文字コードを指定しているEncodingクラスについては、こちらをご覧ください。

WebRequestインスタンスは、WebRequest.Createメソッドで作成します。このとき、指定されたURIによって、適当なWebRequestの派生クラスのインスタンスが返されます。例えば、上記のようにURIのスキームがhttp://またはhttps://の場合は、HttpWebRequestインスタンスを返します。また、file://の場合は、FileWebRequestを返します。さらに、.NET Framework 2.0以降では、ftp://の場合、FtpWebRequestを返します。

非同期でダウンロードする

上記の方法は同期処理のため、受信が完了するまでの間、フリーズしたようになります。これを解決するには、スレッド化するか、非同期処理を行います。ここでは非同期処理の方法について、具体的な例を紹介します。

非同期処理では、まずWebRequest.BeginGetResponseメソッドにより、サーバーからの応答を要求し、待機します。さらに、データを非同期で受信するために、Stream.BeginReadメソッドで読み込みを開始します。

次に示すコンソールアプリケーションのサンプルは、「http://www.yahoo.co.jp」からデータを受信し、表示するものです。非同期要求では自分でタイムアウト処理を行う必要がありますが、このサンプルでは行っていません(WebRequest.TimeoutプロパティはBeginGetResponseメソッドでは無視されます)。詳しくは、下の「参考」をご覧ください。

このような非同期処理を行うには、マルチスレッドプログラミングの知識が必要です。詳しくは、こちらをご覧ください。

VB.NET
コードを隠すコードを選択
Imports System

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 = _
            CType(System.Net.WebRequest.Create( _
            "http://www.yahoo.co.jp"), _
            System.Net.HttpWebRequest)

        '非同期要求を開始
        '状態オブジェクトとしてHttpWebRequestをわたす
        Dim r As IAsyncResult = _
            CType(webreq.BeginGetResponse( _
            New AsyncCallback(AddressOf ResponseCallback), webreq), _
            IAsyncResult)

        '待機する
        Console.ReadLine()
    End Sub

    '非同期要求が終了した時に呼び出されるコールバックメソッド
    Private Shared Sub ResponseCallback(ByVal ar As IAsyncResult)
        '状態オブジェクトとしてわたされたHttpWebRequestを取得
        Dim webreq As System.Net.HttpWebRequest = _
            CType(ar.AsyncState, System.Net.HttpWebRequest)

        '非同期要求を終了
        Dim webres As System.Net.HttpWebResponse = _
            CType(webreq.EndGetResponse(ar), System.Net.HttpWebResponse)

        'ストリームを取得
        Dim st As System.IO.Stream = webres.GetResponseStream()

        'データを読み込むための準備をする
        requestData = New System.IO.MemoryStream
        bufferData = New Byte(1024) {}

        '非同期でデータの読み込みを開始
        '状態オブジェクトとしてStreamをわたす
        Dim r As IAsyncResult = _
            CType(st.BeginRead(bufferData, 0, bufferData.Length, _
            New AsyncCallback(AddressOf ReadCallback), st), _
            IAsyncResult)
    End Sub

    '非同期読み込み完了時に呼び出されるコールバックメソッド
    Private Shared Sub ReadCallback(ByVal ar As IAsyncResult)
        '状態オブジェクトとしてわたされたStreamを取得
        Dim st As System.IO.Stream = _
            CType(ar.AsyncState, System.IO.Stream)

        'データを読み込む
        Dim readSize As Integer = st.EndRead(ar)

        If readSize > 0 Then
            'データが読み込めた時
            '読み込んだデータをMemoryStreamに保存する
            requestData.Write(bufferData, 0, readSize)

            '再び非同期でデータを読み込む
            Dim r As IAsyncResult = _
                CType(st.BeginRead(bufferData, 0, bufferData.Length, _
                New AsyncCallback(AddressOf ReadCallback), st), _
                IAsyncResult)
        Else
            'データの読み込みが終了した時
            'データをデコードして表示する
            Dim enc As System.Text.Encoding = _
                System.Text.Encoding.GetEncoding(51932)
            Console.Write(enc.GetString(requestData.ToArray()))

            '閉じる
            st.Close()
            requestData.Close()
        End If
    End Sub
End Class
C#
コードを隠すコードを選択
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.yahoo.co.jp");

        //非同期要求を開始
        //状態オブジェクトとして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);

            //再び非同期でデータを読み込む
            IAsyncResult r = (IAsyncResult) st.BeginRead(
                bufferData, 0, bufferData.Length,
                new AsyncCallback(ReadCallback), st);
        }
        else
        {
            //データの読み込みが終了した時
            //データをデコードして表示する
            System.Text.Encoding enc =
                System.Text.Encoding.GetEncoding(51932);
            Console.Write(enc.GetString(requestData.ToArray()));

            //閉じる
            st.Close();
            requestData.Close();
        }
    }
}
  • 履歴:
  • 2007/1/20 .NET Framework 2.0に関する記述を追加。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。