通过FTP发送数据

时间:2013-02-15 10:51:48

标签: ios objective-c ftp inputstream

我正在尝试上传文件,我遇到了一些问题。我有一个来自本地路径的输入流:

self.stmIn = [NSInputStream inputStreamWithFileAtPath:localPath];

变量localPath具有以下URL:

/Users/JBG/Library/Application Support/iPhone Simulator/6.0/Applications/734F4DC6-8683-42BB-AB0D-A5553BC22C55/Documents/100046-003.jpg

我可以毫无问题地打开流。当我尝试阅读它时会出现问题:

bytesRead = [self.stmIn read:self.buffer maxLength:kSendBufferSize];

结果是-1。我不明白这个问题。有什么想法吗?

谢谢和问候

编辑:代码是基于Apple的SimpleFTPSample(但是我在UIViewController旁边将其实现为NSObject类)

编辑:使用streamError方法获取此信息:错误域= NSPOSIXErrorDomain代码= 14“操作无法完成。错误的地址”

编辑:我添加了代码:

- (uint8_t *)buffer {
    return self->buffer;
}

- (BOOL)isSending {
    return (self.stmOut != nil);
}

- (void)startSend {
    BOOL success;
    NSURL *url;

    [[NetworkManager sharedInstance] didStartNetworkOperation];

    assert([[NSFileManager defaultManager] fileExistsAtPath:localPath]);

    assert(self.stmOut == nil);      // don't tap send twice in a row!
    assert(self.stmIn == nil);         // ditto

    url = [[NetworkManager sharedInstance] smartURLForString:ftpPath];
    success = (url != nil);

    if (success) {
        url = CFBridgingRelease(CFURLCreateCopyAppendingPathComponent(NULL, (CFURLRef) url, (CFStringRef) [localPath lastPathComponent], false));
        success = (url != nil);
    }

    if ( ! success) {
        NSLog(@"Invalid URL");
    } else {

        self.stmIn = [NSInputStream inputStreamWithFileAtPath:localPath];
        assert(self.stmIn != nil);

        [self.stmIn open];

        self.stmOut = CFBridgingRelease(CFWriteStreamCreateWithFTPURL(NULL, (CFURLRef) url));
        assert(self.stmOut != nil);

        success = [self.stmOut setProperty:ftpUser forKey:(id)kCFStreamPropertyFTPUserName];
        assert(success);
        success = [self.stmOut setProperty:ftpPwd forKey:(id)kCFStreamPropertyFTPPassword];
        assert(success);

        self.stmOut.delegate = self;
        [self.stmOut scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [self.stmOut open];
    }
}

- (void)stopSendWithStatus:(NSString *)statusString {
    if (self.stmOut != nil) {
        [self.stmOut removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        self.stmOut.delegate = nil;
        [self.stmOut close];
        self.stmOut = nil;
    }
    if (self.stmIn != nil) {
        [self.stmIn close];
        self.stmIn = nil;
    }
    if (statusString == nil) {
        statusString = @"Archivo subido";
    }
    [[NetworkManager sharedInstance] didStopNetworkOperation];
}

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
    assert(aStream == self.stmOut);

    switch (eventCode) {
        case NSStreamEventOpenCompleted: {
            NSLog(@"Opened connection");
        } break;
        case NSStreamEventHasBytesAvailable: {
            assert(NO); 
        } break;
        case NSStreamEventHasSpaceAvailable: {
            NSLog(@"Sending");
            if (self.bufferOffset == self.bufferLimit) {
                NSInteger   bytesRead;

                bytesRead = [self.stmIn read:self.buffer maxLength:kSendBufferSize];

                if (bytesRead == -1) {
                    [self stopSendWithStatus:@"File read error"];
                } else if (bytesRead == 0) {
                    [self stopSendWithStatus:nil];
                } else {
                    self.bufferOffset = 0;
                    self.bufferLimit  = bytesRead;
                }
            }

            if (self.bufferOffset != self.bufferLimit) {
                NSInteger   bytesWritten;
                bytesWritten = [self.stmOut write:&self.buffer[self.bufferOffset] maxLength:self.bufferLimit - self.bufferOffset];
                assert(bytesWritten != 0);
                if (bytesWritten == -1) {
                    [self stopSendWithStatus:@"Network write error"];
                } else {
                    self.bufferOffset += bytesWritten;
                }
            }
        } break;
        case NSStreamEventErrorOccurred: {
            [self stopSendWithStatus:@"Stream open error"];
        } break;
        case NSStreamEventEndEncountered: {
        // ignore
        } break;
        default: {
            assert(NO);
        } break;
    }
}

2 个答案:

答案 0 :(得分:1)

试试这段代码..希望它能帮到你..

- (void)sendDidStart
{
    // self.statusLabel.text = @"Sending";
    [[NetworkManager sharedInstance] didStartNetworkOperation];

}

- (void)updateStatus:(NSString *)statusString
{
    assert(statusString != nil);
    //self.statusLabel.text = statusString;
}

- (void)sendDidStopWithStatus:(NSString *)statusString
{
    if (statusString == nil) {
        statusString = @"Put succeeded";
    }
    [[NetworkManager sharedInstance] didStopNetworkOperation];
}

#pragma mark * Core transfer code

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

// Because buffer is declared as an array, you have to use a custom getter.  
// A synthesised getter doesn't compile.

- (uint8_t *)buffer
{
    return self->_buffer;
}

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

- (void)startSend:(NSString *)filePath
{
    BOOL                    success;
    NSURL *                 url;
    NSLog(@"localfilepath..:%@",localFilePath);
    assert(localFilePath != nil);
    assert([[NSFileManager defaultManager] fileExistsAtPath:localFilePath]);
    assert( [localFilePath.pathExtension isEqual:@"png"] || [localFilePath.pathExtension isEqual:@"jpg"] );

    assert(self.networkStream == nil);      // don't tap send twice in a row!
    assert(self.fileStream == nil);         // ditto

    // First get and check the URL.

    url = [[NetworkManager sharedInstance] smartURLForString:@"ftp://yourFTPLink/"];
    success = (url != nil);

    if (success) {
        // Add the last part of the file name to the end of the URL to form the final 
        // URL that we're going to put to.

        // url = CFBridgingRelease(
        // CFURLCreateCopyAppendingPathComponent(NULL, (__bridge CFURLRef) url, (__bridge CFStringRef) @"minkle.png" , false)
        // );
        url = CFBridgingRelease(
                                CFURLCreateCopyAppendingPathComponent(NULL, ( CFURLRef) url, ( CFStringRef) imageString , false)
                                );

        success = (url != nil);
    }

    // If the URL is bogus, let the user know.  Otherwise kick off the connection.

    if ( ! success) {
        // self.statusLabel.text = @"Invalid URL";
    }    
    else 
    {

        // Open a stream for the file we're going to send.  We do not open this stream; 
        // NSURLConnection will do it for us.

        self.fileStream = [NSInputStream inputStreamWithFileAtPath:localFilePath];
        assert(self.fileStream != nil);

        [self.fileStream open];

        // Open a CFFTPStream for the URL.

        self.networkStream = CFBridgingRelease(
                                               CFWriteStreamCreateWithFTPURL(NULL, ( CFURLRef) url)
                                               );
        assert(self.networkStream != nil);

        // if ([self.usernameText.text length] != 0) {
        success = [self.networkStream setProperty:@"yourUserName" forKey:(id)kCFStreamPropertyFTPUserName];
        assert(success);
        success = [self.networkStream setProperty:@"yourPassword" forKey:(id)kCFStreamPropertyFTPPassword];
        assert(success);
        //}

        self.networkStream.delegate = self;
        [self.networkStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [self.networkStream open];

        // Tell the UI we're sending.

        [self sendDidStart];
    }
}

- (void)stopSendWithStatus:(NSString *)statusString
{
    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 sendDidStopWithStatus:statusString];
}

- (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: {
            assert(NO);     // should never happen for the output stream
        } break;
        case NSStreamEventHasSpaceAvailable: {
            [self updateStatus:@"Sending"];

            // If we don't have any data buffered, go read the next chunk of data.

            if (self.bufferOffset == self.bufferLimit) {
                NSInteger   bytesRead;

                bytesRead = [self.fileStream read:self.buffer maxLength:jSendBufferSize];

                if (bytesRead == -1) {
                    [self stopSendWithStatus:@"File read error"];
                } else if (bytesRead == 0) {
                    [self stopSendWithStatus:nil];
                } else {
                    self.bufferOffset = 0;
                    self.bufferLimit  = bytesRead;
                }
            }

            // If we're not out of data completely, send the next chunk.

            if (self.bufferOffset != self.bufferLimit) {
                NSInteger   bytesWritten;
                bytesWritten = [self.networkStream write:&self.buffer[self.bufferOffset] maxLength:self.bufferLimit - self.bufferOffset];
                assert(bytesWritten != 0);
                if (bytesWritten == -1) {
                    [self stopSendWithStatus:@"Network write error"];
                } else {
                    self.bufferOffset += bytesWritten;
                }
            }
        } break;
        case NSStreamEventErrorOccurred: {
            [self stopSendWithStatus:@"Stream open error"];
        } break;
        case NSStreamEventEndEncountered: {
            // ignore
        } break;
        default: {
            assert(NO);
        } break;
    }
}

答案 1 :(得分:0)

你转过这个字符串了吗?

/Users/JBG/Library/Application Support/iPhone Simulator/6.0/Applications/734F4DC6-8683-42BB-AB0D-A5553BC22C55/Documents/100046-003.jpg

到文件网址?

你应该使用[NSURL]中的fileURLWithPath:之类的内容(https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/Reference/Reference .html] docs将字符串路径转换为正确的URL。