[ PHP ] FTP 0バイトファイルの送受信とファイルとディレクトリの判定

Pocket

ここでは、ファイルの FTP によるファイルの送受信と、ファイルとフォルダの判定を行うサンプルスクリプトを掲載しています。

スポンサーリンク

FTP のファイルの送受信を行うサンプル

ファイルの送受信を行うサンプルスクリプトになります。PHP の FTP 関数では GET および PUT コマンドを発行するために、ファイルパスおよびファイルストリーム ( ファイルハンドル ) を指定することができます。サンプルでは、ファイルパスであるか、ストリームであるかを判断してそれぞれ呼び出す関数 ( ftp_fget or ftp_get ) を変更しています。なお、ストリーム とは fopen 関数などのリターン値で返されるファイルハンドルのことを指します。

    /**
     * GET コマンド
     *
     * $local_file  : ローカルファイルパス or stream リソース
     * $remote_file : リモートファイルパス
     * $mode        : FTP_ASCII or FTP_BINARY(デフォルト)
     */
    public function get($conn_id, $local_file, $remote_file, $mode = FTP_BINARY)
    {
        // ストリームリソース(ファイルハンドル)であるかどうかで呼び出し関数を変更する
        if(is_resource($local_file)) {
            return @ftp_fget($conn_id, $local_file, $remote_file, $mode);
        } else {
            return @ftp_get($conn_id, $local_file, $remote_file, $mode);
        }
    }

    /**
     * PUT コマンド
     *
     * $remote_file : リモートファイルパス
     * $local_file  : ローカルファイル ファイルパス or stream リソース
     * $mode        : FTP_ASCII or FTP_BINARY(デフォルト)
     */
    public function put($conn_id, $remote_file, $local_file, $mode = FTP_BINARY)
    {
        // ストリームリソース(ファイルハンドル)であるかどうかで呼び出し関数を変更する
        if(is_resource($local_file)) {
            return @ftp_fput($conn_id, $remote_file, $local_file, $mode);
        } else {
            return @ftp_put($conn_id, $remote_file, $local_file, $mode);
        }
    }
0バイトのファイルの送受信でエラー

FTP で 0 バイトのファイルを送受信する場合には、サーバの実装によっては問題となる場合があります ( 実際にありました ) 。

一部の FTPサーバでは、サイズ 0 バイトのファイルの送受信でレスポンスコードに 225 を返すことがあります。また、関数のリターンコードも false となります。この場合に、以下のワーニングが発生します。

PHP Warning: ftp_fput(): File transfer complete;no transfer in progress in ・・

しかし、サーバ上のリモートファイルでは 0 バイトのファイルが作成されています ( すでに存在する場合は切り詰められます ) 。全ての FTPサーバがそうであるとは限りませんが、FTP のレスポンスコードをスクリプトで取得できないのでリターン値を無視するなど何らかの対処が必要となります。

ftp_nlist: ディレクトリ以外のファイルの一覧を取得する

ftp_nlist 関数でファイルの一覧を取得するとファイルおよびディレクトリの一覧が結果として返されます。本サンプルではディレクトリを除外したファイルのみのリストを取得しています。

ftp_rawlist 関数を使用して詳細なファイル属性を取得して判断する方法もありますが、 Windows と Unix では応答文字列の形式が異なるほか、FTP サーバによっても出力形式が異なるので処理が面倒です。サンプルでは ftp_chdir 関数で実際にカレントディレクトリを移動させています。移動に成功したらディレクトリ、失敗したらファイルとみなして、ファイルのみの一覧を取得しています。

public function nlist($conn_id, $dir = '.', $noDir = true)
{
    // LIST コマンドの発行
    $nlist = ftp_nlist($conn_id, $dir);

    // ディレクトリもリストに含める場合はそのままリターン
    if($noDir === false) { return $nlist; }

    /*
     * ディレクトリを除外する
     */
    $results = array(); 
    foreach ($nlist as $key => $filename) {
    
        /*
         * カレントディレクトリの移動が可能であればディレクトリと判断し、
         * 結果から除外する
         */
        if(@ftp_chdir($conn_id, $filename)) {
        
            // カレントディレクトリを元に戻す(親ディレクトリに移動)
            ftp_cdup($conn_id);
            
        } else {
            // ファイルをリストに追加する
            $results[] = $filename;
        }
    }

    return $results;
}

ftp_chdir 関数のコール時にエラー出力演算子 ( @ ) を使用しているのは、ディレクトリの移動に失敗したときの警告の出力を抑制するためです。

エラー内容

Warning: ftp_chdir(): xxxxxx.xml: Not a directory. in ・・・

参考
スポンサーリンク


Pocket

Leave a Comment

Your email address will not be published. Required fields are marked *