質問させていただきます。
現在、FTP通信を用いて、サーバからiPhoneへとCSV形式のデータをダウンロードできるようにしようと思っています。
ダウンロードする処理自体は完成し、テストサーバを用いてみたところきちんと機能しました。
ですが、本番用のサーバではうまくいきませんでした。
FTPクライアントソフトを用いても本番用のサーバではうまくいかなかったので、原因を調べたところ、
アクティブモードとパッシブモードの違いである事がわかりました。(因に、パッシブモードでは通信失敗、アクティブモードでは成功しました。)
そこで質問なのですが、現在NSURLConectionをもちいてダウンロードしているのですが、通信モードを指定する事は可能なのでしょうか?
もし出来ないのであれば、アクティブモードで通信するにはどうすれば良いでしょうか?
出来れば、質問への答えとともに、どの部分をいじれば良いか、またはどのクラスを使えば良いかを教えていただきたいです。
相互リンク
yahoo知恵袋 http://detail.chiebukuro.yahoo.co.jp/qa ... 1130995266
[objective-c]FTP通信でのモード切り替えについて
Re: [objective-c]FTP通信でのモード切り替えについて
CFFTPStream使えばたぶんできます。
使い方は https://developer.apple.com/library/ios ... Intro.html を見てください。
使い方は https://developer.apple.com/library/ios ... Intro.html を見てください。
Re: [objective-c]FTP通信でのモード切り替えについて
指示された記事をもとにクラスを作成してみたのですが、エラーが出てしまいます。h2so5 さんが書きました:CFFTPStream使えばたぶんできます。
使い方は https://developer.apple.com/library/ios ... Intro.html を見てください。
► スポイラーを表示
Re: [objective-c]FTP通信でのモード切り替えについて
コードを改造してみました。
今回はダウンロードのみ欲しいのでマネージャークラスには変更を加えず、getcontorollerクラスを用いてみました。
エラーは出ないのですがダウンロードは出来てません。
おそらく通信モードが原因なのですが指定する場所が分かりません。
CFreadStreamのsetpropertyメソッドのようなものが存在するのかと思っていたのですが・・・・。
今回はダウンロードのみ欲しいのでマネージャークラスには変更を加えず、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
Re: [objective-c]FTP通信でのモード切り替えについて
今回のソースでは、NSInputStreamを事前に作成し、このストリームに対してCFreadStreamWithFTPURLを設定しています。h2so5 さんが書きました:リファレンス見ましょう
https://developer.apple.com/library/mac ... rence.html
https://developer.apple.com/library/mac ... rence.html
ReadStreamRefに対してなら分かるのですがNSInputStreamは未知すぎて分かりません。
一応実験として
CFReadStreamSetProperty(self.networkStream, //NSinputStream
kCFStreamPropertyFTPUsePassiveMode,
kCFBooleanFalse);
を入力してみたのですがエラーが出てしまいました。(代入する値が違うというエラー)
NSInputStreamの中にReadStreamRefの値を入れる方法が存在するのでしょうか?
Re: [objective-c]FTP通信でのモード切り替えについて
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];