Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
10
Help us understand the problem. What is going on with this article?
@t_oginogin

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

More than 5 years have passed since last update.

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

10
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
t_oginogin
お気に入りは、Ruby、Ruby on Rails

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
10
Help us understand the problem. What is going on with this article?