CocoaでFTPする方法

in

FTPのput機能が必要になる要件があってConnectionKitを使うツモリで調べてたんですがこのFrameworkのサンプルがビルドできなくてアレだったし、Applのサンプルをみたら意外と簡単そうだったので自前で実装してみました。

  1. putするローカルファイルのNSInputStreamを用意する
  2. リモート側に出力するためのNSOutputStreamを用意する
  3. RunLoopのdelegateメソッドを実装する
  4. ストリームの後始末

といった手順になります。入出力のストリームオブジェクトはそれぞれNSIn/OutStreamを使うのですが、出力ストリームが直接生成できない点がポイントでAppleのサンプルではCFWriteStreamCreateWithFTPURLを使ってCFWriteStreamRefを生成した後、NSOutputStreamにキャストしています。

CFWriteStreamRef ftpStream = CFWriteStreamCreateWithFTPURL(NULL, (CFURLRef)url);
remoteOutputStream = (NSOutputStream *)ftpStream;

NSOutputStreamクラスにはCreateWithURLみたいなクラスメソッドが存在せずAppleの作法に従うほかありませんが、最近はHaskellとかやっているのでこういうのはなんだか気持ちが悪いです。ユーザ名やパスワード、プロキシなどのプロパティもこの出力ストリームに設定します。このあたりのことはドキュメントを見つけられませんでしたがキー値はCFFtpStram.hに定義されいています。

[remoteOutputStream setProperty:@"username" forKey:(id)kCFStreamPropertyFTPUserName];
[remoteOutputStream setProperty:@"password" forKey:(id)kCFStreamPropertyFTPPassword];

後はRunLoopをスケジューリングして入出力それぞれのストリームをOpenするだけです。通常、カレントのRunLoopでイベントをとれれば十分だと思います。

[remoteOutputStream setDelegate:self];
[remoteOutputStream scheduleInRunLoop:
  [NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[remoteOutputStream open];

ここで注意なんですが、入出力のストリームはRunLoopのイベント発生時に必要となるためクラスのインスタンス変数として保持しておく必要がありますが出力ストリームを生成するときに使用した、CFWriteStreamRefはリリースする必要があります。(Create Rule)

後はNSStreamDelegateプロトコルに従って、イベントハンドラstream:handleEvent:を実装。実際の出力処理はここで行います。イベントはNSStreamクラスのドキュメントに定義されています。

typedef enum {
   NSStreamEventNone = 0,
   NSStreamEventOpenCompleted = 1 << 0,
   NSStreamEventHasBytesAvailable = 1 << 1,
   NSStreamEventHasSpaceAvailable = 1 << 2,
   NSStreamEventErrorOccurred = 1 << 3,
   NSStreamEventEndEncountered = 1 << 4
};

今回はput機能を実装したかったのでNSStreamEventHasSpaceAvailableに入力ストリームから読んだデータを出力ストリームに書き込む処理を実装しました。Appleのサンプルでは書き込み時はバッファリングしていたのでその通り実装してます。入力ストリームが空になるかエラーが発生したら入出力のストリームを閉じて終了です。

やってみたら簡単ですが、こういうのは何かサンプルがないと難しいです。サンプルはiPhone関連のところにあったりしてiPhone恐るべし….プロトタイプで作成したソースはhttp://github.com/hippos/sampleftpにあります。

sample

この記事のトラックバックURL:

http://hippos-lab.com/blog/trackback/362

Comments

MacでFTPへアップロードする方法を探していてこのサイトにたどり着きました。
サンプルソースをダウンロードし、ソースコードを拝見しました。

私も同じようにiPhoneのサンプルソースにはたどり着いたのですが、未だMacの
ソフト作成しかやっていないため、ちょっと理解できない文法もあり四苦八苦してい
たのですが、サンプルコードを眺めていてアップロードの手順がよくわかりました。

おかげさまで、無事自分のソフトの中にFTPアップロード機能を埋め込むことがで
きました。

貴重な情報、どうもありがとうございました。

貴重な情報、ありがとうございます。とてもたすかります。