通过iphone上的ftp在后台上传文件 [英] upload files in background via ftp on iphone

查看:272
本文介绍了通过iphone上的ftp在后台上传文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在应用内建立FTP连接。我想上传几个文件到一个FTP服务器,所有文件在一个目录中。所以起初我想创建远程目录。

   - (void)createRemoteDir {

NSURL * destinationDirURL = [NSURL URLWithString:uploadDir];

CFWriteStreamRef writeStreamRef = CFWriteStreamCreateWithFTPURL(NULL,(__bridge CFURLRef)destinationDirURL);
assert(writeStreamRef!= NULL);

ftpStream =(__bridge_transfer NSOutputStream *)writeStreamRef;
BOOL成功= [ftpStream setProperty:ftpUser forKey:(id)kCFStreamPropertyFTPUserName];
if(success){
NSLog(@\tsuccessfully set the user name);
}
成功= [ftpStream setProperty:ftpPass forKey:(id)kCFStreamPropertyFTPPassword];
if(成功){
NSLog(@\tsts成功设置密码);
}

ftpStream.delegate = self;
[ftpStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
//打开流
[ftpStream open];
}

使用以下调用在后台线程中执行时,此代码不起作用:

  [self performSelectorInBackground:@selector(createRemoteDir)withObject:nil]; 

我的猜测是(后台线程)runloop没有运行?
如果我在主线程中发送消息,上传可以正常工作:

  [self createRemoteDir]; 

,因为主线程的runloop已启动并正在运行。



但相当大的文件将被上传;所以我想把这个工作负载放在后台线程中。
但是我如何以及在哪里设置NSRunLoop,以便整个上传发生在后台线程中?苹果关于NSRunLoops的文档(特别是如何在没有使用定时器/输入源的情况下启动它们,这种情况下)并没有帮助我。

解决方案
div>

我发现/创建了一个至少适用于我的解决方案。
与上面的方法( createRemoteDir ),下面的代码适用于我:

  NSError *错误; 

createdDirectory = FALSE;
/ *
仅'准备'上传流
- 实际上没有上传任何东西,直到这个后台线程的runloop运行
* /
[self createRemoteDir];

NSRunLoop * currentRunLoop = [NSRunLoop currentRunLoop];

do {

if(![currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]){

// log run error if runloop调用失败
error = [[NSError alloc] initWithDomain:@org.mJae.FTPUploadTrial
code:23
userInfo:nil]; (!createdDirectory&&!error);
}

};

//关闭流,从runloop中移除
[ftpStream close];
[ftpStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

if(error){
//处理错误
}

它运行在后台线程中并在ftp服务器上创建目录。
我比其他例子更喜欢它,runloops只运行一个假定的小时间间隔,比如1秒。

  [ NSDate遥远未来] 

是未来的一个日期(根据Apples文档,几个世纪)。但是,这很好,因为break-condition是由我的类属性 createdDirectory 处理的 - 或者在启动runloop时发生错误。



如果没有明确地将输入源附加到runloop(NSTimer或NSPort),我无法解释为什么它能够工作,但我的猜测是,只需在后台线程的runloop中调度NSOutputStream即可(请参阅 createRemoteDir )。


i'm trying to establish an FTP connection within an app. i want to upload several files to a FTP server, all files in one directory. So at first i want to create the remote directory.

- (void) createRemoteDir {

    NSURL *destinationDirURL = [NSURL URLWithString: uploadDir];

    CFWriteStreamRef writeStreamRef = CFWriteStreamCreateWithFTPURL(NULL, (__bridge CFURLRef) destinationDirURL);
    assert(writeStreamRef != NULL);

    ftpStream = (__bridge_transfer NSOutputStream *) writeStreamRef;
    BOOL success = [ftpStream setProperty: ftpUser forKey: (id)kCFStreamPropertyFTPUserName];
    if (success) {
        NSLog(@"\tsuccessfully set the user name");
    }
    success = [ftpStream setProperty: ftpPass forKey: (id)kCFStreamPropertyFTPPassword];
    if (success) {
        NSLog(@"\tsuccessfully set the password");
    }

    ftpStream.delegate = self;
    [ftpStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    // open stream
    [ftpStream open];
}

This code doesn't work when executed in a background thread using the following call:

[self performSelectorInBackground: @selector(createRemoteDir) withObject: nil];

my guess is that the (background-threads) runloop isn't running? If i send the message inside the main thread the uploading just works fine:

[self createRemoteDir];

as the runloop of the main thread is up and running.

but fairly large files are going to be uploaded; so i want to put that workload in a background thread. but how and where do i set up the NSRunLoop, so that the whole uploading happens in a background thread? Apples documentation on NSRunLoops (especially how to start them without using a timer/input source, as in this case) didn't help me out.

解决方案

I found/created a solution that at least works for me. with the above method (createRemoteDir), the following code applied and worked for me:

NSError *error;

createdDirectory = FALSE;
/* 
 only 'prepares' the stream for upload 
 - doesn't actually upload anything until the runloop of this background thread is run
 */
[self createRemoteDir];

NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];

do {

    if(![currentRunLoop runMode: NSDefaultRunLoopMode beforeDate: [NSDate distantFuture]]) {

        // log error if the runloop invocation failed
        error = [[NSError alloc] initWithDomain: @"org.mJae.FTPUploadTrial" 
                                           code: 23 
                                       userInfo: nil];
    }

} while (!createdDirectory && !error);

// close stream, remove from runloop
[ftpStream close];
[ftpStream removeFromRunLoop: [NSRunLoop currentRunLoop] forMode: NSDefaultRunLoopMode];

if (error) {
    // handle error
}

It runs in a background thread and creates the directory on the ftp server. I like it more than other examples where runloops are only run for an assumed small interval, say 1second.

[NSDate distantFuture]

is a date in the futur (several centuries, according to Apples documentation). But that's good as the "break-condition" is handled by my class property createdDirectory - or the occurance of an error while starting the runloop.

I can't explain why it works without me explicitly attaching an input source to the runloop (NSTimer or NSPort), but my guess is, it is sufficient that the NSOutputStream is scheduled in the runloop of the background thread (see createRemoteDir).

这篇关于通过iphone上的ftp在后台上传文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆