LoginSignup
9
10

More than 5 years have passed since last update.

Objective-CのFTPファイル送受信で日本語名ファイルを扱う

Last updated at Posted at 2014-06-21

Objective-CのFTPファイル送受信で日本語名ファイルを扱う

iOS端末からFTPサーバーにアクセスし、日本語名のファイルを扱う方法をまとめました。
(今回はWindows上のFTPサーバーのファイルにアクセスするケースを想定しています)

準備(FTPライブラリを組み込みます)

FTP送受信のライブラリはGoldRaccoonを使います。

cocoaPodsを使ってインストールするので、まずcocoaPodsをインストールします。

sudo gem install cocoapods

注:rbenvを使っていてエラーになる場合は、systemのrubyを使いましょう。

プロジェクト(例:JapaneaseFTPSample)直下にPodFileを配置します。

PodFile
pod "GoldRaccoon"

GoldRaccoonをインストールします。

pod install

JapaneaseFTPSample.xcworkspaceができているので、これを起動します。

注意点

pod installでインストールしたものが1.0.1の場合、
iPhone Retina(4-inch 64bit)以外で動かすと例外が発生しました。
GitHub上にある最新ソースでは発生しなくなっているのでSources以下を丸ごと置き換えておきましょう。

補足:アップロード時の不具合が修正された1.0.2で最新ソースと一致しています。

FTP機能の利用

List、Get、Putの機能を使ってみます。

組み込み方法はGoldRaccoonの手順と、GRDemoViewControllerの実装を参考にしました。

1.初期化
initWithHostname: user: password:

2.リクエストの登録

addRequestForListDirectoryAtPath:
addRequestForDownloadFileAtRemotePath: toLocalPath:
addRequestForUploadFileAtLocalPath: toRemotePath:

3.リクエストの実行

startProcessingRequests

4.結果受信(デリゲート)

requestsManager: didScheduleRequest:
requestsManager: didCompleteDownloadRequest:
requestsManager: didCompleteListingRequest: listing:
requestsManager: didCompleteUploadRequest:
requestsManager: didFailWritingFileAtPath: forRequest: error:
requestsManager: didFailRequest: withError:

日本語ファイル対応のポイント

ファイルリスト取得時

ファイルリストを取得にはCFFTPCreateParsedResourceListingを使用しています。
この関数で取得されたファイル名はMacRomanに変換して格納されているため、元に戻す必要があります。

このことは、Apple公式サンプルのSimpleFTPSampleのListController.mentryByReencodingNameInEntry:のところで説明されています。

その後本来のエンコードで取り出します。

- (void)requestsManager:(id<GRRequestsManagerProtocol>)requestsManager didCompleteListingRequest:(id<GRRequestProtocol>)request listing:(NSArray *)listing
{
    NSLog(@"requestsManager:didCompleteListingRequest:listing: \n%@", listing);

    self.fileLists = nil;
    self.fileLists = [[NSMutableArray alloc] init];

    // 日本語ファイル名の変換
    NSString *name;
    NSData *nameData;
    NSString *newName;
    for (int i = 0; i<[listing count]; i++) {
        name = listing[i];
        nameData = [name dataUsingEncoding:NSMacOSRomanStringEncoding];
        if (nameData != nil) {
            newName = [[NSString alloc] initWithData:nameData encoding:NSShiftJISStringEncoding];
            [self.fileLists addObject:newName];
        }
    }

    self.getButton.enabled = YES;
    [self.fileListView reloadData];
}

ファイルダウンロード時

ファイル名が日本語なのでURLエンコードする必要があります。
pod installでインストールした1.0.1では自前で対応する必要がありましたが、
GitHubから取得したソースでは内部でエンコードされるようになっていました。

しかしUFT8固定のため、クラス拡張を使ってエンコードすることにしました。

GRRequest+encode.h
#import "GRRequest.h"

@interface GRRequest(Encode)
@end
GRRequest+encode.m
#import "GRRequest+encode.h"
#import <objc/runtime.h>

@implementation GRRequest(Encode)

- (NSString *)encodeString:(NSString *)string;
{
    NSString *urlEncoded = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(
                                                                                                 NULL,
                                                                                                 (__bridge CFStringRef) string,
                                                                                                 NULL,
                                                                                                 (CFStringRef)@"!*'\"();:@&=+$,?%#[]% ",
                                                                                                 kCFStringEncodingMacRoman);
    return urlEncoded;
}

@end

リスト取得時を参考にMacRomanに変換します。

- (IBAction)getFile:(id)sender {
    [self _setupManager];

    if (self.ftpFileName == nil) {
        return;
    }

    NSData *nameData = [self.ftpFileName dataUsingEncoding:NSShiftJISStringEncoding];
    if (nameData == nil) {
        return;
    }

    NSString *fileName = [[NSString alloc] initWithData:nameData encoding:NSMacOSRomanStringEncoding];

    [self.requestsManager addRequestForDownloadFileAtRemotePath:fileName toLocalPath:[NSTemporaryDirectory() stringByAppendingPathComponent:self.ftpFileName]];
    [self.requestsManager startProcessingRequests];
}

ファイルアップロード時

ダウンロード時と同じように変換します。

- (IBAction)putFile:(id)sender {
    [self _setupManager];

    NSData *nameData = [self.ftpFileName dataUsingEncoding:NSShiftJISStringEncoding];
    if (nameData == nil) {
        return;
    }

    NSString *fileName = [[NSString alloc] initWithData:nameData encoding:NSMacOSRomanStringEncoding];

    [self.requestsManager addRequestForUploadFileAtLocalPath:[NSTemporaryDirectory() stringByAppendingPathComponent:self.ftpFileName] toRemotePath:fileName];
    [self.requestsManager startProcessingRequests];
}

今回作成したサンプルコードはGitHubにあげておきます。
JapaneaseFTPSample

9
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
10