[objective-c]FTP通信でのモード切り替えについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
matunon
記事: 64
登録日時: 5年前

[objective-c]FTP通信でのモード切り替えについて

#1

投稿記事 by matunon » 5年前

質問させていただきます。

現在、FTP通信を用いて、サーバからiPhoneへとCSV形式のデータをダウンロードできるようにしようと思っています。
ダウンロードする処理自体は完成し、テストサーバを用いてみたところきちんと機能しました。
ですが、本番用のサーバではうまくいきませんでした。
FTPクライアントソフトを用いても本番用のサーバではうまくいかなかったので、原因を調べたところ、
アクティブモードとパッシブモードの違いである事がわかりました。(因に、パッシブモードでは通信失敗、アクティブモードでは成功しました。)

そこで質問なのですが、現在NSURLConectionをもちいてダウンロードしているのですが、通信モードを指定する事は可能なのでしょうか?
もし出来ないのであれば、アクティブモードで通信するにはどうすれば良いでしょうか?
出来れば、質問への答えとともに、どの部分をいじれば良いか、またはどのクラスを使えば良いかを教えていただきたいです。

相互リンク
yahoo知恵袋  http://detail.chiebukuro.yahoo.co.jp/qa ... 1130995266

アバター
h2so5
副管理人
記事: 2212
登録日時: 8年前
住所: 東京
連絡を取る:

Re: [objective-c]FTP通信でのモード切り替えについて

#2

投稿記事 by h2so5 » 5年前

CFFTPStream使えばたぶんできます。
使い方は https://developer.apple.com/library/ios ... Intro.html を見てください。

matunon
記事: 64
登録日時: 5年前

Re: [objective-c]FTP通信でのモード切り替えについて

#3

投稿記事 by matunon » 5年前

h2so5 さんが書きました:CFFTPStream使えばたぶんできます。
使い方は https://developer.apple.com/library/ios ... Intro.html を見てください。
指示された記事をもとにクラスを作成してみたのですが、エラーが出てしまいます。
► スポイラーを表示

matunon
記事: 64
登録日時: 5年前

Re: [objective-c]FTP通信でのモード切り替えについて

#4

投稿記事 by matunon » 5年前

コードを改造してみました。
今回はダウンロードのみ欲しいのでマネージャークラスには変更を加えず、getcontorollerクラスを用いてみました。
エラーは出ないのですがダウンロードは出来てません。
おそらく通信モードが原因なのですが指定する場所が分かりません。
CFreadStreamのsetpropertyメソッドのようなものが存在するのかと思っていたのですが・・・・。

コード:


#import "GetFTP.h"

#import "NetworkManager.h"

#include <CFNetwork/CFNetwork.h>

@interface GetFTP () <NSStreamDelegate>

@property (nonatomic, assign, readonly ) BOOL isReceiving;
@property (nonatomic, strong, readwrite) NSInputStream *networkStream;
@property (nonatomic, copy,   readwrite) NSString *filePath;
@property (nonatomic) NSData *downloadData;
@property (nonatomic, strong, readwrite) NSOutputStream *fileStream;

@end

@implementation GetFTP

- (void)receiveDidStart
{
    // Clear the current image so that we get a nice visual cue if the receive fails.
    [[NetworkManager sharedInstance] didStartNetworkOperation];
}

- (void)updateStatus:(NSString *)statusString
{
    assert(statusString != nil);
}

- (void)receiveDidStopWithStatus:(NSString *)statusString
{
    if (statusString == nil) {
        assert(self.filePath != nil);
        NSLog(@"GET succeeded");
    }
    
    [[NetworkManager sharedInstance] didStopNetworkOperation];
}

#pragma mark * Core transfer code

// This is the code that actually does the networking.

- (BOOL)isReceiving
{
    return (self.networkStream != nil);
}

- (void)startReceive
// Starts a connection to download the current URL.
{
    
    NSLog(@"startReceive Start");
    
    BOOL                success;
    NSURL *             url;
    
    assert(self.networkStream == nil);      // don't tap receive twice in a row!
    assert(self.fileStream == nil);         // ditto
    assert(self.filePath == nil);           // ditto
    
    // First get and check the URL.
    
    url = [[NetworkManager sharedInstance] smartURLForString:@"ftp://username:password@myserver/vv.csv"];
    success = (url != nil);
    
    // If the URL is bogus, let the user know.  Otherwise kick off the connection.
    
    if ( ! success) {
        NSLog(@"Invalid URL");
    } else {
        
        NSLog(@"OK");
        
        // Open a stream for the file we're going to receive into.
        
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];
        
        self.filePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"naisen.csv"]];

        assert(self.filePath != nil);
        
        self.fileStream = [NSOutputStream outputStreamToFileAtPath:self.filePath append:NO];
        assert(self.fileStream != nil);
        
        [self.fileStream open];
        
        // Open a CFFTPStream for the URL.
        
        self.networkStream = CFBridgingRelease(CFReadStreamCreateWithFTPURL(NULL,
                                                                            (__bridge CFURLRef)url));
        
        assert(self.networkStream != nil);
        
        self.networkStream.delegate = self;
        
        [self.networkStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        
        [self.networkStream open];
        
        // Tell the UI we're receiving.
        
        [self receiveDidStart];
    }
}

- (void)stopReceiveWithStatus:(NSString *)statusString
// Shuts down the connection and displays the result (statusString == nil)
// or the error status (otherwise).
{
    if (self.networkStream != nil) {
        [self.networkStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        self.networkStream.delegate = nil;
        [self.networkStream close];
        self.networkStream = nil;
    }
    if (self.fileStream != nil) {
        [self.fileStream close];
        self.fileStream = nil;
    }
    [self receiveDidStopWithStatus:statusString];
    self.filePath = nil;
}

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
// An NSStream delegate callback that's called when events happen on our
// network stream.
{
#pragma unused(aStream)
    assert(aStream == self.networkStream);
    
    switch (eventCode) {
        case NSStreamEventOpenCompleted: {
            [self updateStatus:@"Opened connection"];
        } break;
        case NSStreamEventHasBytesAvailable: {
            NSInteger       bytesRead;
            uint8_t         buffer[32768];
            
            [self updateStatus:@"Receiving"];
            
            // Pull some data off the network.
            
            bytesRead = [self.networkStream read:buffer maxLength:sizeof(buffer)];
            if (bytesRead == -1) {
                [self stopReceiveWithStatus:@"Network read error"];
            } else if (bytesRead == 0) {
                [self stopReceiveWithStatus:nil];
            } else {
                NSInteger   bytesWritten;
                NSInteger   bytesWrittenSoFar;
                
                // Write to the file.
                
                bytesWrittenSoFar = 0;
                do {
                    bytesWritten = [self.fileStream write:&buffer[bytesWrittenSoFar] maxLength:(NSUInteger) (bytesRead - bytesWrittenSoFar)];
                    assert(bytesWritten != 0);
                    if (bytesWritten == -1) {
                        [self stopReceiveWithStatus:@"File write error"];
                        break;
                    } else {
                        bytesWrittenSoFar += bytesWritten;
                    }
                } while (bytesWrittenSoFar != bytesRead);
            }
        } break;
        case NSStreamEventHasSpaceAvailable: {
            assert(NO);     // should never happen for the output stream
        } break;
        case NSStreamEventErrorOccurred: {
            [self stopReceiveWithStatus:@"Stream open error"];
        } break;
        case NSStreamEventEndEncountered: {
            // ignore
        } break;
        default: {
            assert(NO);
        } break;
    }
}

#pragma mark * UI Actions

- (void)GetDownloadStart
{

    NSLog(@"download");
    
    [self startReceive];

}

- (void)dealloc
{
    [self stopReceiveWithStatus:@"Stopped"];
}

@end




matunon
記事: 64
登録日時: 5年前

Re: [objective-c]FTP通信でのモード切り替えについて

#6

投稿記事 by matunon » 5年前

今回のソースでは、NSInputStreamを事前に作成し、このストリームに対してCFreadStreamWithFTPURLを設定しています。
ReadStreamRefに対してなら分かるのですがNSInputStreamは未知すぎて分かりません。

一応実験として
CFReadStreamSetProperty(self.networkStream, //NSinputStream
kCFStreamPropertyFTPUsePassiveMode,
kCFBooleanFalse);

を入力してみたのですがエラーが出てしまいました。(代入する値が違うというエラー)

NSInputStreamの中にReadStreamRefの値を入れる方法が存在するのでしょうか?

matunon
記事: 64
登録日時: 5年前

Re: [objective-c]FTP通信でのモード切り替えについて

#7

投稿記事 by matunon » 5年前

コード:


self.networkStream = CFBridgingRelease(CFReadStreamCreateWithFTPURL(NULL,
                                                                            (__bridge CFURLRef)url));
        
        CFReadStreamSetProperty(readStream,   //ここでエラー
                                kCFStreamPropertyFTPUserName,
                                (CFTypeRef)@"splanet");
        
        
        CFReadStreamSetProperty(readStream,
                                kCFStreamPropertyFTPPassword,
                                (CFTypeRef)@"spadmin2013$");
        
        CFReadStreamSetProperty(readStream,
                                kCFStreamPropertyFTPUsePassiveMode,
                                kCFBooleanFalse);
        
        self.networkStream = (__bridge NSInputStream *)readStream;
        
        assert(self.networkStream != nil);
        
        self.networkStream.delegate = self;
        
        [self.networkStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        
        [self.networkStream open];

このような感じにしてみたのですが、EXC_BAD_ACCESSエラーが表示されてしまいます。

閉鎖

“C言語何でも質問掲示板” へ戻る