The Backyard - HowtoGetFileFromWebServer Diff
- Added parts are displayed like this.
- Deleted parts are displayed
like this.
この記事は、「WEB+DB PRESS Vol.14」(技術評論社)に掲載していただいた記事の元原稿(必要に応じて加筆/修正/削除をしています)を公開するものです。
!Webサーバー上のファイル情報の取得
NetLauncherは、起動時に同一ディレクトリに存在するassemblyList.xmlを読み込み、指定されたサーバーに対して、最新バージョンが存在するか確認します(リスト:WebFile.cs:NeedUpdateメソッド)。
リスト:WebFile.cs:NeedUpdateメソッド
public bool NeedUpdate(Uri uri)
{
bool result = true;
WebRequest req = WebRequest.Create(uri);
req.Method = "HEAD";
req.Timeout = DefaultTimeout;
req.PreAuthenticate = true;
req.Credentials = CredentialCache.DefaultCredentials;
WebResponse resp = null;
try
{
resp = req.GetResponse();
if (localFile.Exists)
{
string date = resp.Headers["Last-Modified"];
DateTime remoteDate = DateTime.Parse(date);
DateTime localDate = localFile.LastWriteTime;
result = remoteDate > localDate;
}
}
finally
{
if (resp != null) resp.Close();
}
return result;
}
NeedUpdateメソッドは、引数で指定されたURI(ここでは、「http://ホスト/パス名」の形式です)のファイルの情報を取得し、ローカルファイルの更新日付と比較を行います。
.NET FrameworkでHTTPクライアントの機能を提供するのはWebRequestクラスです。このクラスを使用する場合は、4行目のようにファクトリメソッドを呼び出して適切なサブクラスのインスタンスを取得して、それを利用します。この場合、URIのスキーマがHTTP:なので、実際にはHttpWebRequestクラスのインスタンスが返されることになります。
HTTPで主に使用するメソッドは、以下の3種類です。
:GET::GET:ファイル取得要求(HttpWebRequest#Methodの規定値)
:POST::POST:データ送信
:HEAD::HEAD:ファイルのメタデータ要求
ここでは、ファイル日付のチェックが目的ですので、MethodプロパティにHEADを設定します。HEADメソッドを呼び出すと、WebサーバーはGETメソッドから実際のデータを省いた応答を返すため、余分なデータ転送が行われないからです。
7〜8行目では、認証情報の設定を行ってます。PreAuthenticateプロパティにより、あらかじめ認証パラメータを設定して送信することを指示します。Credentialsプロパティに設定している、CredentialCache.DefaultCredentialsは、Windowsへのログインに利用したユーザーID/パスワードおよびドメインです。これは、サーバーがIISの場合には最適な設定となります。なお、サーバーが基本認証を要求する場合には、別途、NetworkCredentialクラスを作成して設定しなければなりません。
POSTメソッドであれば、この後、WebRequest#GetRequestStreamメソッドを呼び出して、送信データを書き込みますが、GETおよびHEADメソッドの場合、9行目のようにすぐにGetResponseメソッドを呼び出して、応答の受信を開始します。GetResponseメソッドから返されるのはWebResponseのサブクラス(この場合、HttpWebResponse)です。なお、ファイルが見つからなかったり(サーバーからのエラー応答を受信)、タイムアウトすると、WebException例外がスローされます。NetLauncherでは、NeedUpdateメソッドの呼び出し元で例外処理を行っているため、ここでは例外のキャッチは行っていません。ただし、WebResponseのCloseメソッドを呼び出さないとリソースリークの原因となるため、finally節を記述して確実に呼び出すようにします。
HTTPでは、ファイルの更新日付は、ヘッダのLast-Modifiedフィールドによって示されます。WebResponseからヘッダのフィールド値を取り出すには12行目のように、Headersインデクサに対して、フィールド名を示す文字列を与えます。もし、ファイルサイズを取得するのであれば、Headersインデクサに"Content-Length"を与えることになります。
!Webサーバーからのファイル受信
既に述べたようにファイルの受信には、GETメソッドを利用します。HEADメソッド呼び出しとの相違は、WebResposneのGetResponseStreamメソッドを呼び出し、受信したデータの読み込みを行う点です(リスト:WebFile.cs:Replaceメソッド)。
リスト:WebFile.cs:Replaceメソッド抜粋
WebRequest req = WebRequest.Create(uri);
req.Method = "GET"; // 規定値なので設定は不要
req.Timeout = DefaultTimeout;
req.PreAuthenticate = true;
req.Credentials = CredentialCache.DefaultCredentials;
WebResponse resp = null;
string tempf = null;
string lastModified = null;
try
{
resp = req.GetResponse();
Stream stm = resp.GetResponseStream();
tempf = Path.GetTempFileName();
using (FileStream dest = new FileStream(tempf, FileMode.Create))
{
byte[] buff = new Byte[8000];
int len = 0;
while ((len = stm.Read(buff, 0, buff.Length)) > 0)
{
dest.Write(buff, 0, len);
}
}
lastModified = resp.Headers["Last-Modified"];
}
finally
{
if (resp != null) resp.Close();
}
なお、WebResponse#Closeの呼び出しで、WebResponse#GetResponseStreamが返すストリーム(リストでは変数名stmで記されます)も同時にクローズされるため、明示的なstmのClose呼び出しを省略しています。ただし、記述してもエラーとはなりません。
!Webサーバー上のファイル情報の取得
NetLauncherは、起動時に同一ディレクトリに存在するassemblyList.xmlを読み込み、指定されたサーバーに対して、最新バージョンが存在するか確認します(リスト:WebFile.cs:NeedUpdateメソッド)。
リスト:WebFile.cs:NeedUpdateメソッド
public bool NeedUpdate(Uri uri)
{
bool result = true;
WebRequest req = WebRequest.Create(uri);
req.Method = "HEAD";
req.Timeout = DefaultTimeout;
req.PreAuthenticate = true;
req.Credentials = CredentialCache.DefaultCredentials;
WebResponse resp = null;
try
{
resp = req.GetResponse();
if (localFile.Exists)
{
string date = resp.Headers["Last-Modified"];
DateTime remoteDate = DateTime.Parse(date);
DateTime localDate = localFile.LastWriteTime;
result = remoteDate > localDate;
}
}
finally
{
if (resp != null) resp.Close();
}
return result;
}
NeedUpdateメソッドは、引数で指定されたURI(ここでは、「http://ホスト/パス名」の形式です)のファイルの情報を取得し、ローカルファイルの更新日付と比較を行います。
.NET FrameworkでHTTPクライアントの機能を提供するのはWebRequestクラスです。このクラスを使用する場合は、4行目のようにファクトリメソッドを呼び出して適切なサブクラスのインスタンスを取得して、それを利用します。この場合、URIのスキーマがHTTP:なので、実際にはHttpWebRequestクラスのインスタンスが返されることになります。
HTTPで主に使用するメソッドは、以下の3種類です。
ここでは、ファイル日付のチェックが目的ですので、MethodプロパティにHEADを設定します。HEADメソッドを呼び出すと、WebサーバーはGETメソッドから実際のデータを省いた応答を返すため、余分なデータ転送が行われないからです。
7〜8行目では、認証情報の設定を行ってます。PreAuthenticateプロパティにより、あらかじめ認証パラメータを設定して送信することを指示します。Credentialsプロパティに設定している、CredentialCache.DefaultCredentialsは、Windowsへのログインに利用したユーザーID/パスワードおよびドメインです。これは、サーバーがIISの場合には最適な設定となります。なお、サーバーが基本認証を要求する場合には、別途、NetworkCredentialクラスを作成して設定しなければなりません。
POSTメソッドであれば、この後、WebRequest#GetRequestStreamメソッドを呼び出して、送信データを書き込みますが、GETおよびHEADメソッドの場合、9行目のようにすぐにGetResponseメソッドを呼び出して、応答の受信を開始します。GetResponseメソッドから返されるのはWebResponseのサブクラス(この場合、HttpWebResponse)です。なお、ファイルが見つからなかったり(サーバーからのエラー応答を受信)、タイムアウトすると、WebException例外がスローされます。NetLauncherでは、NeedUpdateメソッドの呼び出し元で例外処理を行っているため、ここでは例外のキャッチは行っていません。ただし、WebResponseのCloseメソッドを呼び出さないとリソースリークの原因となるため、finally節を記述して確実に呼び出すようにします。
HTTPでは、ファイルの更新日付は、ヘッダのLast-Modifiedフィールドによって示されます。WebResponseからヘッダのフィールド値を取り出すには12行目のように、Headersインデクサに対して、フィールド名を示す文字列を与えます。もし、ファイルサイズを取得するのであれば、Headersインデクサに"Content-Length"を与えることになります。
!Webサーバーからのファイル受信
既に述べたようにファイルの受信には、GETメソッドを利用します。HEADメソッド呼び出しとの相違は、WebResposneのGetResponseStreamメソッドを呼び出し、受信したデータの読み込みを行う点です(リスト:WebFile.cs:Replaceメソッド)。
リスト:WebFile.cs:Replaceメソッド抜粋
WebRequest req = WebRequest.Create(uri);
req.Method = "GET"; // 規定値なので設定は不要
req.Timeout = DefaultTimeout;
req.PreAuthenticate = true;
req.Credentials = CredentialCache.DefaultCredentials;
WebResponse resp = null;
string tempf = null;
string lastModified = null;
try
{
resp = req.GetResponse();
Stream stm = resp.GetResponseStream();
tempf = Path.GetTempFileName();
using (FileStream dest = new FileStream(tempf, FileMode.Create))
{
byte[] buff = new Byte[8000];
int len = 0;
while ((len = stm.Read(buff, 0, buff.Length)) > 0)
{
dest.Write(buff, 0, len);
}
}
lastModified = resp.Headers["Last-Modified"];
}
finally
{
if (resp != null) resp.Close();
}
なお、WebResponse#Closeの呼び出しで、WebResponse#GetResponseStreamが返すストリーム(リストでは変数名stmで記されます)も同時にクローズされるため、明示的なstmのClose呼び出しを省略しています。ただし、記述してもエラーとはなりません。