.NET TIPS

FTPでエラーが発生した場合に生のメッセージを取得するには?[2.0のみ、C#、VB]

デジタルアドバンテージ 遠藤 孝信
2006/06/23

 「TIPS:WebRequest/WebResponseクラスでFTPによりファイル転送を行うには?」で示した方法によりFTPでファイル転送を行っていてFTPサーバでエラーが発生した場合には、WebRequestクラスのGetResponseメソッドなどで例外が発生する(記事中では省略しているが通常はtry-catch構文による例外処理を実装すべきだ)。

 このとき、どのような内容のエラーが発生したかは例外オブジェクト(Exceptionクラス(System名前空間)、あるいはその派生クラスのオブジェクト)のMessageプロパティから知ることができるのだが、FTPの場合には.NET FrameworkがFTPサーバから返されたエラー内容を汎用的なメッセージに置き換えてしまい、エラーの内容が分かりにくい場合がある。

分かりにくいFTPのエラー・メッセージ

 例えば次のサンプル・プログラムは、あるFTPサーバのあるディレクトリ配下に新しいディレクトリを3回作成しようとして、2回目と3回目がエラーになる例だ。

// ftpstatus.cs

using System;
using System.Net;

class FtpStatus {
  static void Main() {

    string url;
    string id = "user01";
    string pw = "mypassword";

    // /uploadは書き込み可能なディレクトリであるとする
    url = "ftp://servername/upload/mynewdir";
    FtpMakeDir(url, id, pw); // 成功

    // 再度同じディレクトリを作成
    url = "ftp://servername/upload/mynewdir";
    FtpMakeDir(url, id, pw); // 失敗

    // /usrはアクセス権のないディレクトリであるとする
    url = "ftp://servername/usr/mynewdir";
    FtpMakeDir(url, id, pw); // 失敗
  }

  static void FtpMakeDir(string url, string id, string pw) {
    WebRequest req = WebRequest.Create(url);
    req.Credentials = new NetworkCredential(id, pw);
    req.Method = WebRequestMethods.Ftp.MakeDirectory;

    try {
      WebResponse res = req.GetResponse();
    } catch (WebException e) {
      Console.WriteLine(e.Message);
    }
  }
}

// コンパイル方法:ftpstatus.cs
FTPでディレクトリを作成しようとしてエラーとなるC#のサンプル・プログラム(ftpstatus.cs)

' ftpstatus.vb

Imports System
Imports System.Net

Class FtpStatus
  Shared Sub main()
    Dim url As String
    Dim id As String = "user01"
    Dim pw As String = "mypassword"

    ' /uploadは書き込み可能なディレクトリであるとする
    url = "ftp://servername/upload/mynewdir"
    FtpMakeDir(url, id, pw) ' 成功

    ' 再度同じディレクトリを作成
    url = "ftp://servername/upload/mynewdir"
    FtpMakeDir(url, id, pw) ' 失敗

    ' /usrはアクセス権のないディレクトリであるとする
    url = "ftp://servername/usr/mynewdir"
    FtpMakeDir(url, id, pw) '失敗
  End Sub

  Shared Sub FtpMakeDir(ByVal url As String, ByVal id As String, ByVal pw As String)
    Dim req As WebRequest = WebRequest.Create(url)
    req.Credentials = New NetworkCredential(id, pw)
    req.Method = WebRequestMethods.Ftp.MakeDirectory

    Try
      Dim res As WebResponse = req.GetResponse()
    Catch e As WebException
      Console.WriteLine(e.Message)
    End Try
  End Sub
End Class

' コンパイル方法:vbc ftpstatus.vb
FTPでディレクトリを作成しようとしてエラーとなるVBのサンプル・プログラム(ftpstatus.vb)

 ここでWebExceptionクラス(System.Net名前空間)は、WebRequest/WebResponseクラス(あるいはそれらの派生クラス)で発生する例外のクラスである。

 このプログラムでは、2回目はすでに同名のディレクトリが存在するため、3回目はディレクトリにアクセス権がないためにエラーとなるのだが、どちらの場合も画面に表示されるe.Messageの内容は次のようになる。

リモート サーバーがエラーを返しました: (550) ファイルが使用できません (例: ファイルが見つからない、ファイルへのアクセスがない)
上記サンプル・プログラムで表示されるエラー・メッセージ

 「550」はFTPのステータス・コード(レスポンス・コードと呼ばれる場合もある)を示すものだが*、.NET Frameworkのエラー・メッセージはステータス・コードのみにより決められているようだ。

* FTPのステータス・コードの一覧は、RFC 959「FILE TRANSFER PROTOCOL (FTP)」4.2.1 Reply Codes by Function Groupsで参照できる。

生のメッセージを含むStatusDescriptionプロパティ

 しかしたいていのFTPサーバでは、例えば同じ550番でも実際にはよりエラー内容に即したメッセージを返しており、そのメッセージを見るとエラーの原因が分かりやすい。

 そのようなFTPサーバからの生のメッセージは、FtpWebResponseオブジェクトのStatusDescriptionプロパティから取得することができる。

 また、WebException例外がFTPによるファイル転送時に発生した場合には、そのResponseプロパティにはFTPサーバからのレスポンスを示すFtpWebResponseオブジェクトがセットされている。

 従って、上記のFtpMakeDirメソッドを以下のように修正すれば、エラー発生時にFTPサーバが返す生のメッセージを表示させることができる。

static void FtpMakeDir(string url, string id, string pw) {
  WebRequest req = WebRequest.Create(url);
  req.Credentials = new NetworkCredential(id, pw);
  req.Method = WebRequestMethods.Ftp.MakeDirectory;

  try {
    WebResponse res = req.GetResponse();
  } catch (WebException e) {
    FtpWebResponse res = (FtpWebResponse)e.Response;
    Console.WriteLine(res.StatusDescription);
  }
}
Shared Sub FtpMakeDir(ByVal url As String, ByVal id As String, ByVal pw As String)
  Dim req As WebRequest = WebRequest.Create(url)
  req.Credentials = New NetworkCredential(id, pw)
  req.Method = WebRequestMethods.Ftp.MakeDirectory


  Try
    Dim res As WebResponse = req.GetResponse()
  Catch e As WebException
    Dim res As FtpWebResponse = CType(e.Response, FtpWebResponse)
    Console.WriteLine(res.StatusDescription)
  End Try
End Sub
エラー時にFTPサーバが返した生のメッセージを表示するFtpMakeDirメソッド(上:C#、下:VB)

 こちらのメソッドを使うと、筆者が試したFTPサーバでは2回目、3回目のエラー・メッセージはそれぞれ以下のような内容だった。

550 Permission denied to "mynewdir".
2回目のエラー・メッセージ

550 "/usr/": Access denied.
3回目のエラー・メッセージ

 使用するFTPサーバによりメッセージ内容が変わってしまう、FTPサーバによってはメッセージが日本語でないなどの欠点はあるが、エラーの原因を探るには有用だろう。End of Article

利用可能バージョン:.NET Framework 2.0のみ
カテゴリ:クラス・ライブラリ 処理対象:ネットワーク
使用ライブラリ:WebRequestクラス(System.Net名前空間)
使用ライブラリ:WebResponseクラス(System.Net名前空間)
使用ライブラリ:NetworkCredentialクラス(System.Net名前空間)
関連TIPS:WebRequest/WebResponseクラスでFTPによりファイル転送を行うには?

この記事と関連性の高い別の.NET TIPS
WebClientクラスでFTPによりファイル転送を行うには?
FTP時にディレクトリの存在を調べるには?
WebRequest/WebResponseクラスでFTPによりファイル転送を行うには?
Webサーバのプロトコル違反による例外を回避するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間