CocoaでFTPする方法
FTPのput機能が必要になる要件があってConnectionKitを使うツモリで調べてたんですがこのFrameworkのサンプルがビルドできなくてアレだったし、Applのサンプルをみたら意外と簡単そうだったので自前で実装してみました。
- putするローカルファイルのNSInputStreamを用意する
- リモート側に出力するためのNSOutputStreamを用意する
- RunLoopのdelegateメソッドを実装する
- ストリームの後始末
といった手順になります。入出力のストリームオブジェクトはそれぞれ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にあります。



最近のコメント
14 weeks 4 days ago
49 weeks 2 days ago
1年 14 weeks ago
1年 14 weeks ago
1年 31 weeks ago
1年 31 weeks ago
1年 31 weeks ago
1年 43 weeks ago
1年 43 weeks ago
2 years 23 weeks ago